/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   Module Name          : com.yaodian100.ec.generate.service.impl.GenerateServiceImpl
   Module Description   :

   Date Created      : 2009/12/29
   Original Author   : feeling.wang
   Team              : yaodian100
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   MODIFICATION HISTORY
   ------------------------------------------------------------------------------
   Date Modified       Modified by       Comments
   ------------------------------------------------------------------------------
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
package com.yaodian100.ec.generate.service.impl;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.Reader;
import java.io.Serializable;
import java.io.StringReader;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;

import javax.annotation.Resource;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.RandomUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;

import com.yaodian100.core.admin.entity.User;
import com.yaodian100.core.admin.entity.UserPermission;
import com.yaodian100.core.admin.entity.Permission.Type;
import com.yaodian100.core.admin.service.UserService;
import com.yaodian100.core.admin.utils.AdminHelper;
import com.yaodian100.core.common.dao.ObjectDao;
import com.yaodian100.core.common.dao.impl.CommonCriteria;
import com.yaodian100.core.common.exception.CoreException;
import com.yaodian100.core.common.service.BaseManager;
import com.yaodian100.core.common.service.impl.DomainServiceImpl;
import com.yaodian100.core.common.utils.ServerValue;
import com.yaodian100.core.mail.service.MailService;
import com.yaodian100.core.menu.entity.Menu;
import com.yaodian100.core.menu.service.MenuService;
import com.yaodian100.core.template.service.TemplateService;
import com.yaodian100.ec.announcement.entity.Announcement;
import com.yaodian100.ec.announcement.service.AnnouncementService;
import com.yaodian100.ec.category.entity.Category;
import com.yaodian100.ec.category.service.CategoryService;
import com.yaodian100.ec.generate.entity.EventImage;
import com.yaodian100.ec.generate.entity.GenerateAdvertise;
import com.yaodian100.ec.generate.entity.GenerateContent;
import com.yaodian100.ec.generate.entity.GeneratePosition;
import com.yaodian100.ec.generate.entity.ViewPmAdvertise;
import com.yaodian100.ec.generate.entity.ViewPromotionAdvertise;
import com.yaodian100.ec.generate.service.GenerateNotifyService;
import com.yaodian100.ec.generate.service.GenerateService;
import com.yaodian100.ec.product.entity.ProdCatRC;
import com.yaodian100.ec.product.entity.Product;
import com.yaodian100.ec.product.service.DaphneProductService;
import com.yaodian100.ec.product.service.ProductRCService;
import com.yaodian100.ec.product.service.ProductService;
import com.yaodian100.ec.rank.entity.ViewReportProductClick;
import com.yaodian100.ec.report.rank.service.ViewReportProductClickService;
import com.yaodian100.ec.search.entity.Keyword;
import com.yaodian100.ec.search.entity.KeywordDefault;
import com.yaodian100.ec.search.service.KeywordService;
import com.yaodian100.ec.shelf.entity.Shelf;
import com.yaodian100.ec.shelf.entity.ViewFlagProduct;
import com.yaodian100.ec.shelf.entity.ViewShelf;
import com.yaodian100.ec.shelf.entity.ViewShelfProduct;
import com.yaodian100.ec.shelf.service.ShelfService;

/**
 * @author feeling.wang
 * 
 */
public class GenerateServiceImpl extends DomainServiceImpl<GenerateAdvertise> implements GenerateService {
	private static final String MENU_KEY_CATEGORY_GROUP_MAPPING = "Category.Group.Mapping";
	private static final String ROLE_AD_CONTACT_WINDOW = "AD_CONTACT_WINDOW";
	private static final String VM_AD_PRODUCT_SHELF_INACTIVE_NOTIFICATION = "ad_product_shelf_inactive_notification";
	private ObjectDao<GeneratePosition> generatePositionDao;
	private ObjectDao<GenerateContent> generateContentDao;
	private ObjectDao<EventImage> eventImageDao;
	private ObjectDao<ViewPromotionAdvertise> viewPromotionAdvertiseDao;
	private ShelfService shelfService;
	private CategoryService categoryService;
	private ObjectDao<Product> productDao;
	private ObjectDao<ViewPmAdvertise> viewPmAdvertiseDao;
	@Autowired
	private TemplateService templateService;
	@Autowired
	private MenuService menuService;
	@Autowired
	private KeywordService keywordService;
	private AnnouncementService announcementService;
	@Autowired
	private MailService mailService;
	@Autowired
	private UserService userService;
	@Autowired
	private DaphneProductService daphneService;
	@Autowired
	private JdbcTemplate jdbcTemplate;
	@Resource
	private BaseManager baseMgr;
	@Autowired
	private ViewReportProductClickService viewReportProductClickService;
	@Autowired
	private ProductService productService;
	@Autowired
	private ProductRCService productRCService;
	@Autowired
	private GenerateNotifyService generateNotifyService;

	// private ArrayList<String> tempProdIds;
	// private List<ViewPromotionAdvertise> viewPromotionAdvs;
	// private Properties prop = null;
	// private Reader reader = null;
	// private StringBuilder sbFilePath = null;
	// private List<Shelf> shelfList;
	final String subFileName = ".html";

	private final String STRING_SYMBOL = "/";

	// private Map<String, Shelf> shelfMap;

	/**
	 * 將 integer 轉為指定長度
	 * 
	 * @param value
	 * @param size
	 * @return
	 */
	private String converInt(Long value, int size) {
		StringBuffer sb = new StringBuffer();
		int div = 1;
		for (int i = 0; i < size; i++) {
			if ((value / div) % 10 == 0) {
				sb.insert(0, "0");
			} else {
				sb.insert(0, (value / div) % 10);
			}
			div = div * 10;
		}
		return sb.toString();
	}

	/**
	 * 刪除檔案
	 * 
	 * @param filePath
	 * @param fileName
	 * @return
	 * @throws IOException
	 */
	boolean deleteFiles(String filePath, final String fileName) {
		try {
			File file = new File(filePath);
			File[] files = file.listFiles(new FilenameFilter() {
				@Override
				public boolean accept(File dir, String name) {
					return !name.startsWith(fileName + "_1") && name.startsWith(fileName);
				}
			});

			if (null != files) {
				for (int i = 0; i < files.length; i++) {
					FileUtils.forceDelete(files[i]);
				}
			}
		} catch (Exception e) {
			logger.error("deleteFiles exception:{}", e.fillInStackTrace());
			return false;
		}
		return true;
	}

	/**
	 * 刪除上、中、下位置的檔案
	 * 
	 * @param filePath
	 * @param fileName
	 * @return
	 */
	boolean deleteFilesOfPosition(String filePath, final String fileName) {
		try {
			File file = new File(filePath);
			File[] files = file.listFiles(new FilenameFilter() {
				@Override
				public boolean accept(File dir, String name) {
					return !name.startsWith(fileName + "TOP_1") && !name.startsWith(fileName + "MID_1")
							&& !name.startsWith(fileName + "BTM_1") && name.startsWith(fileName);
				}
			});

			if (null != files) {
				for (int i = 0; i < files.length; i++) {
					FileUtils.forceDelete(files[i]);
				}
			}
		} catch (Exception e) {
			logger.error("deleteFilesOfPosition exception:{}", e.fillInStackTrace());
			return false;
		}
		return true;
	}

	boolean generateBannerAdv(CommonCriteria criteria) throws CoreException {
		try {
			List<ViewPromotionAdvertise> viewPromotionAdvs = getViewPromotionAdvertiseDao().getList(criteria,
					new String[] { "startDate", "advTarget" });
			if (viewPromotionAdvs.size() > 0) {
				Map<String, Object> bannerMap = null;
				String cateId = "";
				int k = 0, x = 1, y = 1, z = 1;
				GenerateAdvertise advertise = null;
				boolean mkdirResult = false;
				StringBuilder sbFilePath = null;
				Reader reader = null;
				Properties prop = null;
				for (ViewPromotionAdvertise viewPromotionAdv : viewPromotionAdvs) {
					sbFilePath = new StringBuilder();
					prop = new Properties();
					reader = new StringReader(viewPromotionAdv.getContents());
					prop.load(reader);
					reader.close();
					bannerMap = new HashMap<String, Object>();
					bannerMap.put("prop", prop);
					bannerMap.put("advType", viewPromotionAdv.getAdvType());
					if ("TOP".equalsIgnoreCase(viewPromotionAdv.getAdvTarget())) {
						k = x++;
					} else if ("MID".equalsIgnoreCase(viewPromotionAdv.getAdvTarget())) {
						k = y++;
					} else if ("BTM".equalsIgnoreCase(viewPromotionAdv.getAdvTarget())) {
						k = z++;
					}
					if (StringUtils.equalsIgnoreCase(viewPromotionAdv.getAdvType(), "100_BANNER")) {
						cateId = viewPromotionAdv.getChildCateId().toString();
					} else {
						cateId = viewPromotionAdv.getMainCateId().toString();
					}

					mkdirResult = mkGenerateHtmlDir(viewPromotionAdv.getAdvType(), cateId);
					if (mkdirResult) {
						sbFilePath.append(ServerValue.getFrontContentHtmlPath()).append(cateId).append(File.separator).append(
								viewPromotionAdv.getAdvType().split("_")[1]).append("_").append(viewPromotionAdv.getAdvTarget())
								.append("_").append(k).append(subFileName);

						// 先寫檔再update db
						FileUtils.writeStringToFile(new File(sbFilePath.toString()), templateService.format(
								"static_CategoryBanner", bannerMap));
						sbFilePath.setLength(0);
						// update 廣告狀態為20(放送中-前3個才會被update)
						if (k <= 3) {
							advertise = getDao().get(Long.parseLong(String.valueOf(viewPromotionAdv.getId())));
							advertise.setAdvStatus("20");
							getDao().update(advertise);
						}

					}
				}
			}
		} catch (Exception e) {
			logger.error("generateBanner Advexception:{}", e.fillInStackTrace());
		}
		return true;
	}

	@Override
	public boolean generateCategoryIndexV2(String date) throws CoreException {
		try {
			Date tmp;
			if (StringUtils.isNotBlank(date)) {
				tmp = new java.text.SimpleDateFormat("yyyyMMddHHmmss").parse(date);
			} else {
				tmp = new Date();
			}
			CommonCriteria criteria = new CommonCriteria();
			criteria.addIn("level", Arrays.asList("0", "1"));
			criteria.addEq("isVisible", "Y");
			criteria.addEq("isDelete", "N");
			criteria.addLe("startDate", tmp);
			criteria.addGe("endDate", tmp);
			List<Category> catTemp = categoryService.getList(0, -1, criteria, new String[] { "parentId asc", "showSeq asc" });

			List<Category> categories = new ArrayList<Category>();
			Hashtable<Long, List<Category>> subH = new Hashtable<Long, List<Category>>();
			List<Category> sub_categories;
			for (Category cat : catTemp) {
				if (cat.getParentId().intValue() == 0) {
					categories.add(cat);
				} else {
					if (subH.containsKey(cat.getParentId())) {
						sub_categories = subH.get(cat.getParentId());
					} else {
						sub_categories = new ArrayList<Category>();
					}
					sub_categories.add(cat);
					subH.put(cat.getParentId(), sub_categories);
				}
			}

			Map<String, Object> m = new HashMap<String, Object>();
			m.put("contentPath", ServerValue.getFrontContextPath());
			m.put("categories", categories);
			m.put("subH", subH);
			FileUtils.writeStringToFile(new File(ServerValue.getFrontContentHtmlPath() + File.separator + "COMMON"
					+ File.separator + "CATEGORY_INDEX_V2.html"), templateService.format("static_CategoryIndex", m));
		} catch (Exception e) {
			logger.error(e.getMessage());
			return false;
		}
		return true;
	}

	@Override
	public boolean generateDaphneCategoryIndex(String date) throws CoreException {
		List<String> dpList = daphneService.getAvailableDaphneCategory();
		try {
			Date tmp;
			if (StringUtils.isNotBlank(date)) {
				tmp = new java.text.SimpleDateFormat("yyyyMMddHHmmss").parse(date);
			} else {
				tmp = new Date();
			}
			CommonCriteria criteria = new CommonCriteria();
			criteria.addEq("parentId", Long.parseLong("0"));
			criteria.addEq("isVisible", "Y");
			criteria.addEq("isDelete", "N");
			criteria.addLe("startDate", tmp);
			criteria.addGe("endDate", tmp);
			List<Category> categories = categoryService.getList(0, -1, criteria, new String[] { "showSeq asc" });
			List<Category> categorieD = new ArrayList<Category>();
			for (Category cat : categories) {
				if (dpList.contains(Long.toString(cat.getId()))) {
					categorieD.add(cat);
				}
			}

			Hashtable<Long, List<Category>> subH = new Hashtable<Long, List<Category>>();
			for (Category cat : categorieD) {
				// create sub menu
				criteria = new CommonCriteria();
				criteria.addEq("parentId", cat.getId());
				criteria.addEq("isVisible", "Y");
				criteria.addEq("isDelete", "N");
				criteria.addLe("startDate", new Date());
				criteria.addGe("endDate", new Date());
				List<Category> sub_categories = categoryService.getList(0, -1, criteria, new String[] { "showSeq asc" });
				List<Category> sub_categoriesD = new ArrayList<Category>();
				for (Category sub_cat : sub_categories) {
					if (dpList.contains(Long.toString(sub_cat.getId()))) {
						sub_categoriesD.add(sub_cat);
					}
				}
				subH.put(cat.getId(), sub_categoriesD);
			}
			Map<String, Object> m = new HashMap<String, Object>();
			m.put("contentPath", ServerValue.getFrontContextPath());
			m.put("categories", categorieD);
			m.put("subH", subH);
			FileUtils.writeStringToFile(new File(ServerValue.getFrontContentHtmlPath() + File.separator + "COMMON"
					+ File.separator + "DAPHNE_CATEGORY_INDEX.html"), templateService.format("static_DaphneCategoryIndex", m));
		} catch (Exception e) {
			logger.error(e.getMessage());
			return false;
		}
		return true;
	}

	/**
	 * Index、館首頁黃金大看版
	 * 
	 * @param criteria
	 * @return
	 * @throws CoreException
	 */
	boolean generateCateMainGoldAdv(CommonCriteria criteria) throws CoreException {
		try {
			List<ViewPromotionAdvertise> viewPromotionAdvs = getViewPromotionAdvertiseDao().getList(criteria,
					new String[] { "startDate", "advTarget" });
			GenerateAdvertise advertise = null;
			String cateId = "";
			int k = 0;
			Map<String, Object> mainGoldMap = null;
			StringBuilder sbFilePath = null;
			Reader reader = null;
			Properties prop = null;
			for (ViewPromotionAdvertise viewPromotionAdv : viewPromotionAdvs) {
				cateId = viewPromotionAdv.getMainCateId().toString();
				sbFilePath = new StringBuilder();
				prop = new Properties();
				reader = new StringReader(viewPromotionAdv.getContents());
				prop.load(reader);
				reader.close();
				mainGoldMap = new HashMap<String, Object>();
				mainGoldMap.put("props", prop);
				mainGoldMap.put("contentPath", ServerValue.getFrontContextPath());
				mainGoldMap.put("categoryId", cateId);
				k++;
				boolean mkdirResult = mkGenerateHtmlDir(viewPromotionAdv.getAdvType(), cateId);
				if (mkdirResult) {
					sbFilePath.append(ServerValue.getFrontContentHtmlPath()).append(cateId).append(File.separator).append(
							viewPromotionAdv.getAdvType()).append("_").append(k).append(subFileName);
					FileUtils.writeStringToFile(new File(sbFilePath.toString()), templateService.format("static_CateMainGold",
							mainGoldMap));
					sbFilePath.setLength(0);
					// update 廣告狀態為20(放送中-前3個才會被update)
					if (k <= 3) {
						advertise = getDao().get(Long.parseLong(String.valueOf(viewPromotionAdv.getId())));
						advertise.setAdvStatus("20");
						getDao().update(advertise);
					}
				}
			}
		} catch (Exception e) {
			logger.error("generateCateMainGoldAdv exception:{}", e.fillInStackTrace());
			return false;
		}
		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.generate.service.GenerateService#generateMainCateMainGoldAdv_V2(java.lang.String)
	 */
	@Override
	@Transactional(readOnly = false)
	public void generateCateMainGoldAdv(String date) throws CoreException {
		String advType = "000_MAINGOLD_V2";
		CommonCriteria criteria = new CommonCriteria();
		criteria.addEq("parentId", 0l);
		criteria.addEq("isDelete", "N");
		List<Category> categories = categoryService.getList(0, -1, criteria, new String[] { "id" });
		for (Category category : categories) {
			boolean result = deleteFiles(ServerValue.getFrontContentHtmlPath() + category.getId().toString(), advType);
			if (result) {
				criteria = new CommonCriteria();
				criteria.addEq("advType", advType);
				criteria.addEq("mainCateId", category.getId());
				generateCateMainGoldAdv(criteria);
			}
		}
	}

	@Override
	public boolean generateCuratorRecommV2(Long categoryId) throws CoreException, IOException {
		Category category = null;
		if (categoryId != null && categoryId.longValue() != 0) {
			category = categoryService.getCategoryById(categoryId);
		}

		CommonCriteria cri = new CommonCriteria();
		if (category != null) {
			cri.addRlike("categoryPath", category.getCategoryPath());
		}
		List<String> genedCatId = new ArrayList<String>();
		cri.addEq("flag16", "Y"); // 取出所有馆长推荐商品 (flag16=Y)
		List<ViewFlagProduct> vfpList = shelfService.getViewFlagProduct(cri, new String[] { "shelfModifyDate" }, 0, -1);
		Hashtable<String, List<ViewFlagProduct>> vfpH = new Hashtable<String, List<ViewFlagProduct>>();
		if (null != vfpList && vfpList.size() > 0) {
			// 分类
			for (ViewFlagProduct vfp : vfpList) {
				String[] tmp = vfp.getCategoryPath().split("/");
				List<ViewFlagProduct> promote;
				if (tmp.length >= 2) {
					String key = tmp[0];
					for (int i = 1; i < tmp.length; i++) {
						key = key + "/" + tmp[i];
						if (vfpH.containsKey(key)) {
							promote = vfpH.get(key);
						} else {
							promote = new ArrayList<ViewFlagProduct>();
						}
						if (!promote.contains(vfp)) {
							promote.add(vfp);
						}
						vfpH.put(key, promote);
					}
				}
			}
			Enumeration<String> keys = vfpH.keys();
			while (keys.hasMoreElements()) {
				String key = keys.nextElement();
				String[] tmp = key.split("/");
				String nowCatId = tmp[tmp.length - 1];
				genedCatId.add(nowCatId);
				List<ViewFlagProduct> promotetmp = vfpH.get(key);
				List<ViewFlagProduct> promote = new ArrayList<ViewFlagProduct>();
				int base = promotetmp.size();
				if (base > 3) {
					do {
						int r = RandomUtils.nextInt(base);
						if (!promote.contains(promotetmp.get(r))) {
							promote.add(promotetmp.get(r));
						}
					} while (promote.size() < 3);
				} else {
					promote = promotetmp;
				}
				Map<String, Object> m = new HashMap<String, Object>();
				m.put("contentPath", ServerValue.getFrontContextPath());
				m.put("viewFlagProductList", promote);
				// 刪除原本的檔案
				File file = new File(ServerValue.getFrontContentHtmlPath() + nowCatId + File.separator + "RECOMMEND_V2.html");
				if (file.exists()) {
					FileUtils.forceDelete(file);
				}
				FileUtils.writeStringToFile(new File(ServerValue.getFrontContentHtmlPath() + nowCatId + File.separator
						+ "RECOMMEND_V2.html"), templateService.format("static_CuratorRecommend_V2", m));
			}
		}
		// 删除没有馆长推荐的分类
		List<Category> categories = categoryService.getSideBarAvailableCategory();
		for (Category cat : categories) {
			if ((!cat.getLevel().equals("0")) && (!genedCatId.contains(cat.getId().toString()))) {
				File file = new File(ServerValue.getFrontContentHtmlPath() + cat.getId().toString() + File.separator
						+ "RECOMMEND_V2.html");
				if (file.exists()) {
					FileUtils.forceDelete(file);
				}
			}
		}
		return true;
	}

	@Override
	@Transactional(readOnly = false)
	public boolean generateCuratorRecommV3(String categoryId) throws CoreException, IOException {
		CommonCriteria crit = new CommonCriteria();
		crit.addEq("categoryId", categoryId);
		crit.addNe("sortOrder", null);
		String[] sortArray = new String[] { "sortOrder desc" };
		List productRCList = productRCService.getList(0, -1, crit, sortArray);

		List<ProdCatRC> randomList = new ArrayList<ProdCatRC>();
		for (int i = 0; i < productRCList.size(); i++) {
			ProdCatRC prodCatRC = (ProdCatRC) productRCList.get(i);
			// 檢核館長推薦商品是否還上架，並將參數prodCatRC同步最新資料(ex.商品小標...等)
			boolean isExist = productRCService.checkCateProdRC(prodCatRC);
			if (isExist) {
				// 將最新同步資料，update至館長推薦table
				productRCService.update(prodCatRC);

				randomList.add(prodCatRC);
			} else {
				productRCService.delete(prodCatRC);
			}
		}

		int randomListSize = randomList.size();
		List<ProdCatRC> showList = new ArrayList<ProdCatRC>();
		if (randomListSize > 3) {
			double randomCnt = Math.pow(2, randomListSize) - 1;
			Map keyMap = new TreeMap();
			while (showList.size() < 3) {
				int randomInt = (int) ((Math.random() * randomCnt) + 1);
				for (int i = 0; i < randomListSize; i++) {
					randomInt = randomInt - (int) (Math.pow(2, i));
					if (randomInt <= 0 && !keyMap.containsKey(i)) {
						keyMap.put(i, i);
						showList.add(randomList.get(i));
						break;
					}
				}
			}
		} else {
			showList = randomList;
		}

		Map<String, Object> m = new HashMap<String, Object>();
		m.put("contentPath", ServerValue.getFrontContextPath());
		m.put("showList", showList);
		// 刪除原本的檔案
		File file = new File(ServerValue.getFrontContentHtmlPath() + "PRODUCTRC" + File.separator + categoryId
				+ File.separator + "RECOMMEND_V3.html");
		if (file.exists()) {
			FileUtils.forceDelete(file);
		}

		if (showList.size() > 0) {
			FileUtils
					.writeStringToFile(new File(ServerValue.getFrontContentHtmlPath() + "PRODUCTRC" + File.separator + categoryId
							+ File.separator + "RECOMMEND_V3.html"), templateService.format("static_CuratorRecommend_V3", m));
		}

		return true;
	}

	@Override
	@Transactional(readOnly = false)
	public boolean generateHotSelectV2(Long categoryId) throws CoreException, IOException {
		List<ViewPromotionAdvertise> viewPromotionAdvs = null;
		List<Category> categories = null;

		if (categoryId != null && categoryId != 0) {
			categories = new ArrayList<Category>();
			categories.add(categoryService.getCategoryById(categoryId));
		} else {
			categories = categoryService.getAvailableSameLevelCategory(Long.parseLong("0"), "0");
		}

		for (Category category : categories) {
			// 刪除原本的檔案
			File file = new File(ServerValue.getFrontContentHtmlPath() + category.getId() + File.separator
					+ "HOTSELECT_V2.html");
			if (file.exists()) {
				FileUtils.forceDelete(file);
			}
			CommonCriteria criteria = new CommonCriteria();
			criteria.addEq("advType", "000_HOTSELECT");
			criteria.addEq("mainCateId", category.getId());
			criteria.addLe("startDate", new Date());
			criteria.addGe("endDate", new Date());
			String nowCat = category.getId().toString();
			viewPromotionAdvs = getViewPromotionAdvertiseDao().getList(criteria, new String[] { "modifyDate desc" });
			if (viewPromotionAdvs.size() > 0) {
				Reader reader = null;
				Properties prop = null;
				Map<String, Object> m = new HashMap<String, Object>();
				List<Map<String, String>> proudctList = new ArrayList<Map<String, String>>();
				for (int j = viewPromotionAdvs.size() - 1; j >= 0; j--) {
					ViewPromotionAdvertise viewPromotionAdv = viewPromotionAdvs.get(j);
					GenerateAdvertise advertise = getDao().get(Long.parseLong(String.valueOf(viewPromotionAdv.getId())));
					List<String> productIdList = new ArrayList<String>();
					if (j < 3) {
						prop = new Properties();
						reader = new StringReader(viewPromotionAdv.getContents());
						prop.load(reader);
						reader.close();

						Map<String, String> prodMap = null;
						Product p;
						Shelf s;
						String pid;
						for (int i = 1; i <= 5; i++) {
							prodMap = new HashMap<String, String>();
							if (prop.containsKey("tab" + i + "ProdId")) {
								pid = prop.getProperty("tab" + i + "ProdId");
								p = productDao.get(pid);
								s = shelfService.getActiveShelfByProductId(pid);
								prodMap.put("productId", pid);
								prodMap.put("imgName", prop.getProperty("tab" + i + "ImgName"));
								prodMap.put("imgFolder", prop.getProperty("tab" + i + "ImgFolder"));
								prodMap.put("brief", prop.getProperty("tab" + i + "Brief"));
								prodMap.put("name", prop.getProperty("tab" + i + "Name"));
								prodMap.put("tagType", StringUtils.defaultString(prop.getProperty("tab" + i + "TagType")));
								prodMap.put("tagName", StringUtils.defaultString(prop.getProperty("tab" + i + "TagName")));
								if (null != p && null != s) {
									prodMap.put("listPrice", p.getListPrice().toString());
									prodMap.put("isSoldOut", p.getIsSoldOut().toString());
									prodMap.put("shelfPrice", s.getShelfPrice().toString());
								} else {
									productIdList.add(pid);
								}
								proudctList.add(prodMap);
							}
						}

						advertise.setAdvStatus("20");
						getDao().update(advertise);
					} else {
						advertise.setAdvStatus("10");
						getDao().update(advertise);
					}

					// 检核商品并寄发错误通知信
					generateNotifyService.sendNotificationForProductIdsWithProblem(category.getId(), productIdList,
							viewPromotionAdv.getAdvType(), viewPromotionAdv.getAdvName());
				}
				m.put("contentPath", ServerValue.getFrontContextPath());
				m.put("advType", "000_HOTSELECT");
				m.put("proudctList", proudctList);
				m.put("categoryId", category.getId());

				FileUtils.writeStringToFile(new File(ServerValue.getFrontContentHtmlPath() + nowCat + File.separator
						+ "HOTSELECT_V2.html"), templateService.format("static_HotSelect_V2", m));
			}
		}
		return true;
	}

	@Override
	@Transactional(readOnly = false)
	public void generateIdxGoldFourV2(String date) throws CoreException, Exception {
		deleteFiles(ServerValue.getFrontContentHtmlPath() + "IDX", "IDX_GOLDFOUR_V2");
		deleteFiles(ServerValue.getFrontContentHtmlPath() + "IDX", "IDX_GOLDFOUR_V3");
		CommonCriteria criteria = new CommonCriteria();
		criteria.addEq("advType", "IDX_GOLDFOUR_V2");
		criteria.addLe("startDate", new Date());
		criteria.addGe("endDate", new Date());
		List<ViewPromotionAdvertise> viewPromotionAdvs = getViewPromotionAdvertiseDao().getList(criteria, null);
		if (viewPromotionAdvs.size() > 0) {
			int k = 1;
			Reader reader = null;
			Properties prop = null;
			List<Long> updateList = new ArrayList<Long>();
			for (ViewPromotionAdvertise viewPromotionAdv : viewPromotionAdvs) {
				prop = new Properties();
				reader = new StringReader(viewPromotionAdv.getContents());
				prop.load(reader);
				reader.close();
				Map<String, Object> m = new HashMap<String, Object>();
				m.put("contentPath", ServerValue.getFrontContextPath());
				m.put("prop", prop);
				m.put("advType", viewPromotionAdv.getAdvType());
				FileUtils.writeStringToFile(new File(ServerValue.getFrontContentHtmlPath() + "IDX" + File.separator
						+ "IDX_GOLDFOUR_V2_" + k + ".html"), templateService.format("static_GoldFour_V2", m));
				FileUtils.writeStringToFile(new File(ServerValue.getFrontContentHtmlPath() + "IDX" + File.separator
						+ "IDX_GOLDFOUR_V3_" + k + ".html"), templateService.format("static_GoldFour_V3", m));
				updateList.add(Long.parseLong(String.valueOf(viewPromotionAdv.getId())));
				k++;
				// GenerateAdvertise advertise = getDao().get(Long.parseLong(String.valueOf(viewPromotionAdv.getId())));
				// advertise.setAdvStatus("20");
				// getDao().update(advertise);
			}
			if (updateList.size() > 0) {
				updateAdvStatus("IDX_GOLDFOUR_V2", updateList);
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.generate.service.GenerateService#generateIdxHotSaleV2(java.lang.String)
	 */
	@Override
	@Transactional(readOnly = false)
	public void generateIdxHotSaleV2(String date) throws CoreException, Exception {
		deleteFiles(ServerValue.getFrontContentHtmlPath() + "IDX", "IDX_HOTSALE_V2");
		deleteFiles(ServerValue.getFrontContentHtmlPath() + "IDX", "IDX_HOTSALE_V3");
		CommonCriteria criteria = new CommonCriteria();
		String adType = "IDX_HOTSALE_V2";
		criteria.addEq("advType", adType);
		criteria.addLe("startDate", new Date());
		criteria.addGe("endDate", new Date());
		List<ViewPromotionAdvertise> viewPromotionAdvs = getViewPromotionAdvertiseDao().getList(criteria, null);
		if (viewPromotionAdvs.size() > 0) {
			int k = 1;
			ArrayList<Long> list = new ArrayList<Long>();
			Reader reader = null;
			Properties prop = null;
			for (ViewPromotionAdvertise viewPromotionAdv : viewPromotionAdvs) {
				prop = new Properties();
				reader = new StringReader(viewPromotionAdv.getContents());
				prop.load(reader);
				reader.close();
				Hashtable<String, String> priceH = new Hashtable<String, String>();
				List<String> productIdList = new ArrayList<String>();
				for (int i = 1; i <= 4; i++) {
					CommonCriteria criteria2 = new CommonCriteria();
					criteria2.addEq("productId", prop.getProperty("tab" + i + "ProdId"));
					criteria2.addEq("isDelete", "N");
					List<ViewShelfProduct> viewShelfProducts = shelfService.getViewShelfProduct(criteria2, null, 0, 1);
					if (null != viewShelfProducts && viewShelfProducts.size() > 0) {
						ViewShelfProduct vsp = viewShelfProducts.get(0);
						priceH.put(vsp.getProductId(), vsp.getShelfPrice().setScale(2).toString());
					}
					String productId = prop.getProperty("tab" + i + "ProdId");
					productIdList.add(productId);
				}
				Map<String, Object> m = new HashMap<String, Object>();
				m.put("contentPath", ServerValue.getFrontContextPath());
				m.put("prop", prop);
				m.put("priceH", priceH);
				FileUtils.writeStringToFile(new File(ServerValue.getFrontContentHtmlPath() + "IDX" + File.separator
						+ "IDX_HOTSALE_V2_" + k + ".html"), templateService.format("static_HotSale_V2", m));
				FileUtils.writeStringToFile(new File(ServerValue.getFrontContentHtmlPath() + "IDX" + File.separator
						+ "IDX_HOTSALE_V3_" + k + ".html"), templateService.format("static_HotSale_V3", m));
				k++;
				list.add(Long.parseLong(String.valueOf(viewPromotionAdv.getId())));
				// GenerateAdvertise advertise = getDao().get(Long.parseLong(String.valueOf(viewPromotionAdv.getId())));
				// advertise.setAdvStatus("20");
				// getDao().update(advertise);

				// 检核商品并寄发错误通知信
				generateNotifyService.sendNotificationForProductIdsWithProblem(Long.parseLong("0"), productIdList,
						viewPromotionAdv.getAdvType(), viewPromotionAdv.getAdvName());
			}
			if (list.size() > 0) {
				updateAdvStatus(adType, list);
			}
		}
	}

	/**
	 * Index、館首頁黃金大看版
	 * 
	 * @param criteria
	 * @return
	 * @throws CoreException
	 */
	boolean generateIdxMainGoldAdv_V2(CommonCriteria criteria) throws CoreException {
		try {
			List<ViewPromotionAdvertise> viewPromotionAdvs = getViewPromotionAdvertiseDao().getListPageable(criteria,
					new String[] { "showSeq asc", "startDate", "advTarget" }, 0, 6);
			if (viewPromotionAdvs.size() > 0) {
				List<Long> updateList = new ArrayList<Long>();
				GenerateAdvertise advertise = null;
				String cateId = "IDX";
				String advType = "IDX_MAINGOLD_V2";
				Map<String, Object> mainGoldMap = new HashMap<String, Object>();
				StringBuilder sbFilePath = null;
				Reader reader = null;
				Properties prop = null;
				List<Properties> props = new ArrayList<Properties>();
				for (ViewPromotionAdvertise viewPromotionAdv : viewPromotionAdvs) {
					updateList.add(Long.parseLong(String.valueOf(viewPromotionAdv.getId())));
					prop = new Properties();
					reader = new StringReader(viewPromotionAdv.getContents());
					prop.load(reader);
					reader.close();
					props.add(prop);
				}
				mainGoldMap.put("advType", advType);
				mainGoldMap.put("props", props);
				mainGoldMap.put("contentPath", ServerValue.getFrontContextPath());

				boolean mkdirResult = mkGenerateHtmlDir(advType, cateId);
				if (mkdirResult) {
					sbFilePath = new StringBuilder();
					sbFilePath.append(ServerValue.getFrontContentHtmlPath()).append(cateId).append(File.separator)
							.append(advType).append(subFileName);
					FileUtils.writeStringToFile(new File(sbFilePath.toString()), templateService.format("static_IdxMainGold",
							mainGoldMap));
					sbFilePath = new StringBuilder();
					sbFilePath.append(ServerValue.getFrontContentHtmlPath()).append(cateId).append(File.separator).append(
							advType.replace('2', '3')).append(subFileName);
					FileUtils.writeStringToFile(new File(sbFilePath.toString()), templateService.format("static_IdxMainGold_V3",
							mainGoldMap));
					sbFilePath.setLength(0);
					// update 廣告狀態為20(放送中-前6個才會被update)
					// for (ViewPromotionAdvertise viewPromotionAdv : viewPromotionAdvs) {
					// advertise = getDao().get(Long.parseLong(String.valueOf(viewPromotionAdv.getId())));
					// advertise.setAdvStatus("20");
					// getDao().update(advertise);
					// }
					if (updateList.size() > 0) {
						updateAdvStatus(advType, updateList);
					}
				}
			}
		} catch (Exception e) {
			logger.error("generateIdxMainGoldAdv exception:{}", e.fillInStackTrace());
			return false;
		}
		return true;
	}

	boolean generateIdxMainGoldAdv_V2(String domain, String advType) throws CoreException {
		try {
			boolean isIdx = false;
			// 主站advType
			String advType2 = "IDX_MAINGOLD_V2";
			String cateId = domain + File.separator + "IDX";

			CommonCriteria criteria = new CommonCriteria();
			criteria.addEq("advType", advType);
			List<ViewPromotionAdvertise> viewPromotionAdvs = getViewPromotionAdvertiseDao().getListPageable(criteria,
					new String[] { "showSeq asc", "startDate", "advTarget" }, 0, 6);

			// 如果PCLady没资料，抓yaodian100的
			if (viewPromotionAdvs.size() == 0) {
				isIdx = true;
				criteria = new CommonCriteria();
				criteria.addEq("advType", advType2);
				viewPromotionAdvs = getViewPromotionAdvertiseDao().getListPageable(criteria,
						new String[] { "showSeq asc", "startDate", "advTarget" }, 0, 6);
			}

			if (viewPromotionAdvs.size() > 0) {
				List<Long> updateList = new ArrayList<Long>();
				GenerateAdvertise advertise = null;

				Map<String, Object> mainGoldMap = new HashMap<String, Object>();
				StringBuilder sbFilePath = null;
				Reader reader = null;
				Properties prop = null;
				List<Properties> props = new ArrayList<Properties>();
				for (ViewPromotionAdvertise viewPromotionAdv : viewPromotionAdvs) {
					updateList.add(Long.parseLong(String.valueOf(viewPromotionAdv.getId())));
					prop = new Properties();
					reader = new StringReader(viewPromotionAdv.getContents());
					prop.load(reader);
					reader.close();
					props.add(prop);
				}
				if (isIdx) {
					mainGoldMap.put("advType", advType2);
				} else {
					mainGoldMap.put("advType", advType);
				}
				mainGoldMap.put("props", props);
				mainGoldMap.put("contentPath", ServerValue.getFrontContextPath());

				boolean mkdirResult = mkGenerateHtmlDir(advType, cateId);
				if (mkdirResult) {
					sbFilePath = new StringBuilder();
					sbFilePath.append(ServerValue.getFrontContentHtmlPath()).append(cateId).append(File.separator).append(
							advType2).append(subFileName);
					FileUtils.writeStringToFile(new File(sbFilePath.toString()), templateService.format("static_IdxMainGold",
							mainGoldMap).replaceAll("http://www.yaodian100.com", ""));
					sbFilePath = new StringBuilder();
					sbFilePath.append(ServerValue.getFrontContentHtmlPath()).append(cateId).append(File.separator).append(
							advType2.replace('2', '3')).append(subFileName);
					FileUtils.writeStringToFile(new File(sbFilePath.toString()), templateService.format("static_IdxMainGold_V3",
							mainGoldMap).replaceAll("http://www.yaodian100.com", ""));
					sbFilePath.setLength(0);
					// update 廣告狀態為20(放送中-前6個才會被update)
					// for (ViewPromotionAdvertise viewPromotionAdv : viewPromotionAdvs) {
					// advertise = getDao().get(Long.parseLong(String.valueOf(viewPromotionAdv.getId())));
					// advertise.setAdvStatus("20");
					// getDao().update(advertise);
					// }
					if (updateList.size() > 0) {
						updateAdvStatus(advType, updateList);
					}
				}
			}
		} catch (Exception e) {
			logger.error("generateIdxMainGoldAdv exception:{}", e.fillInStackTrace());
			return false;
		}
		return true;
	}

	/**
	 * 品牌折扣馆 - 厂商Banner
	 * 
	 * @param criteria
	 * @return
	 * @throws CoreException
	 */
	boolean generateOutletsBannerAdv(CommonCriteria criteria) throws CoreException {
		try {
			List<ViewPromotionAdvertise> viewPromotionAdvs = getViewPromotionAdvertiseDao().getListPageable(criteria,
					new String[] { "showSeq asc", "startDate", "advTarget" }, 0, 3);
			if (viewPromotionAdvs.size() > 0) {
				List<Long> updateList = new ArrayList<Long>();
				String cateId = "7447";
				String advType = "OUTLETS_BANNER";
				Map<String, Object> mainGoldMap = new HashMap<String, Object>();
				StringBuilder sbFilePath = null;
				Reader reader = null;
				Properties prop = null;
				List<Properties> props = new ArrayList<Properties>();
				for (ViewPromotionAdvertise viewPromotionAdv : viewPromotionAdvs) {
					updateList.add(Long.parseLong(String.valueOf(viewPromotionAdv.getId())));
					prop = new Properties();
					reader = new StringReader(viewPromotionAdv.getContents());
					prop.load(reader);
					reader.close();
					props.add(prop);
				}
				mainGoldMap.put("props", props);
				mainGoldMap.put("contentPath", ServerValue.getFrontContextPath());

				boolean mkdirResult = mkGenerateHtmlDir(advType, cateId);
				if (mkdirResult) {
					sbFilePath = new StringBuilder();
					sbFilePath.append(ServerValue.getFrontContentHtmlPath()).append(cateId).append(File.separator)
							.append(advType).append(subFileName);
					FileUtils.writeStringToFile(new File(sbFilePath.toString()), templateService.format("static_OutletsBanner",
							mainGoldMap));
					sbFilePath.setLength(0);

					if (updateList.size() > 0) {
						updateAdvStatus(advType, updateList);
					}
				}
			}
		} catch (Exception e) {
			logger.error("generateOutletsBannerAdv exception:{}", e.fillInStackTrace());
			return false;
		}
		return true;
	}

	@Override
	@Transactional(readOnly = false)
	public void generateIdxMainGoldAdv_V2(String date) throws CoreException {
		// boolean result = deleteFiles(ServerValue.getFrontContentHtmlPath() + "IDX", "MAINGOLD_V2");
		// if (result) {
		CommonCriteria criteria = new CommonCriteria();
		criteria.addEq("advType", "IDX_MAINGOLD_V2");
		generateIdxMainGoldAdv_V2(criteria);
		// }
	}

	@Override
	@Transactional(readOnly = false)
	public void generatePclMainGoldAdv_V2(String date) throws CoreException {
		Menu menu = menuService.get("SystemValue");
		generateIdxMainGoldAdv_V2(menu.getOptions().get("pclady").getMemo1(), "PCL_MAINGOLD_V2");
	}

	@Override
	@Transactional(readOnly = false)
	public void generateOutletsBannerAdv() throws CoreException {
		CommonCriteria criteria = new CommonCriteria();
		criteria.addEq("advType", "OUTLETS_BANNER");
		generateOutletsBannerAdv(criteria);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.generate.service.GenerateService#generateIdxNews(java.lang.String)
	 */
	@Override
	public void generateIdxNews(String date) throws CoreException, Exception {
		deleteFiles(ServerValue.getFrontContentHtmlPath() + "IDX", "NEWS");
		Date tmp;
		if (StringUtils.isNotBlank(date)) {
			tmp = new java.text.SimpleDateFormat("yyyyMMddHHmmss").parse(date);
		} else {
			tmp = new Date();
		}
		CommonCriteria criteria = new CommonCriteria();
		criteria.addEq("type", "MYYAODIAN");
		criteria.addEq("isDelete", "N");
		criteria.addLe("startDate", tmp);
		criteria.addGe("endDate", tmp);
		List<Announcement> newslist = announcementService.getList(0, 3, criteria, new String[] { "showSeq asc",
				"modifyDate desc" });
		Map<String, Object> m = new HashMap<String, Object>();
		m.put("contentPath", ServerValue.getFrontContextPath());
		m.put("newslist", newslist);
		FileUtils.writeStringToFile(new File(ServerValue.getFrontContentHtmlPath() + "IDX" + File.separator + "NEWS.html"),
				templateService.format("static_news", m));
		FileUtils.writeStringToFile(new File(ServerValue.getFrontContentHtmlPath() + "IDX" + File.separator
				+ "NEWS_V3.html"), templateService.format("static_News_V3", m));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.generate.service.GenerateService#generateIndexTab3()
	 */
	@Override
	public void generateIndexTab3(String date) throws CoreException {
		Menu header = menuService.get("Generate.tab3.index");
		try {
			deleteFiles(ServerValue.getFrontContentHtmlPath() + "IDX", "RANKINGLIST");
			List<ViewFlagProduct> promote1 = null, promote2 = null, promote3 = null;

			/*
			 * P. 右側熱銷商品(tab 1) ProductPromotionFlag.flag04 Q. 右側店長推荐(tab 2) ProductPromotionFlag.flag05 R. 右側街頭熱賣(tab 3)
			 * ProductPromotionFlag.flag06
			 */
			try {
				List<ViewFlagProduct> promote1T = shelfService.getViewFlagProduct(null, new String[] { "flag04 desc",
						"shelfModifyDate" }, 0, 600);
				List<ViewFlagProduct> promote2T = shelfService.getViewFlagProduct(null, new String[] { "flag05 desc",
						"shelfModifyDate" }, 0, 600);
				List<ViewFlagProduct> promote3T = shelfService.getViewFlagProduct(null, new String[] { "flag06 desc",
						"shelfModifyDate" }, 0, 600);
				promote1 = new ArrayList();
				promote2 = new ArrayList();
				promote3 = new ArrayList();
				int base = promote1T.size();
				do {
					int r = RandomUtils.nextInt(base);
					if (!promote1.contains(promote1T.get(r))) {
						promote1.add(promote1T.get(r));
					}
				} while (promote1.size() < 12);

				do {
					int r = RandomUtils.nextInt(base);
					if (!promote2.contains(promote2T.get(r))) {
						promote2.add(promote2T.get(r));
					}
				} while (promote2.size() < 12);

				do {
					int r = RandomUtils.nextInt(base);
					if (!promote3.contains(promote3T.get(r))) {
						promote3.add(promote3T.get(r));
					}
				} while (promote3.size() < 12);

			} catch (CoreException e) {
				logger.warn("get promote empty, msg:{}", e.getMessage());
				promote1 = new ArrayList();
				promote2 = new ArrayList();
				promote3 = new ArrayList();
			}

			if (promote1.size() > 0 && promote2.size() > 0 && promote3.size() > 0) {
				File folder = new File(ServerValue.getFrontContentHtmlPath() + File.separator + "IDX");
				if (!folder.exists()) {
					folder.mkdirs();
				}

				Map m = new HashMap();
				m.put("contextPath", ServerValue.getFrontContextPath());
				if (header != null) {
					m.put("head1", header.getOptions().get("tab1").getName());
					m.put("head2", header.getOptions().get("tab2").getName());
					m.put("head3", header.getOptions().get("tab3").getName());
				} else {
					m.put("head1", null);
					m.put("head2", null);
					m.put("head3", null);
				}

				for (int i = 0; i < 3; i++) {
					m.put("product1List", promote1.subList(i * 4, (i + 1) * 4 - 1));
					m.put("product2List", promote2.subList(i * 4, (i + 1) * 4 - 1));
					m.put("product3List", promote3.subList(i * 4, (i + 1) * 4 - 1));
					String fileData = templateService.format("static_Tab3", m);
					File file = new File(ServerValue.getFrontContentHtmlPath() + File.separator + "IDX" + File.separator
							+ "RANKINGLIST_" + (i + 1) + ".html");
					file.createNewFile();
					FileUtils.writeByteArrayToFile(file, fileData.getBytes());
				}
			} else {
				logger.warn("promote is empty, promote1:{},promote2:{},promote3:{}", new Object[] { promote1.size(),
						promote2.size(), promote3.size() });
			}

		} catch (IOException e) {
			logger.error("write file error", e);
			throw new CoreException("write file error", e);
		}
	}

	@Override
	public void generateIndexTab3V2(String date) throws CoreException {
		Menu header = menuService.get("Generate.tab3.index");
		try {
			deleteFiles(ServerValue.getFrontContentHtmlPath() + "IDX", "IDX_RANKINGLIST_V2");
			List<ViewFlagProduct> promote1 = null, promote2 = null, promote3 = null;

			/*
			 * P. 右側熱銷商品(tab 1) ProductPromotionFlag.flag04 Q. 右側店長推荐(tab 2) ProductPromotionFlag.flag05 R. 右側街頭熱賣(tab 3)
			 * ProductPromotionFlag.flag06
			 */
			try {

				List<ViewFlagProduct> promote1T = shelfService.getViewFlagProductForIdxTab3(date, "flag04 desc", 0, 400);
				List<ViewFlagProduct> promote2T = shelfService.getViewFlagProductForIdxTab3(date, "flag05 desc", 0, 400);
				List<ViewFlagProduct> promote3T = shelfService.getViewFlagProductForIdxTab3(date, "flag06 desc", 0, 400);
				promote1 = new ArrayList();
				promote2 = new ArrayList();
				promote3 = new ArrayList();
				int base = promote1T.size();
				do {
					int r = RandomUtils.nextInt(base);
					if (!promote1.contains(promote1T.get(r))) {
						promote1.add(promote1T.get(r));
					}
				} while (promote1.size() < 12);

				do {
					int r = RandomUtils.nextInt(base);
					if (!promote2.contains(promote2T.get(r))) {
						promote2.add(promote2T.get(r));
					}
				} while (promote2.size() < 12);

				do {
					int r = RandomUtils.nextInt(base);
					if (!promote3.contains(promote3T.get(r))) {
						promote3.add(promote3T.get(r));
					}
				} while (promote3.size() < 12);

			} catch (CoreException e) {
				logger.warn("get promote empty, msg:{}", e.getMessage());
				promote1 = new ArrayList();
				promote2 = new ArrayList();
				promote3 = new ArrayList();
			}

			if (promote1.size() > 0 && promote2.size() > 0 && promote3.size() > 0) {
				File folder = new File(ServerValue.getFrontContentHtmlPath() + File.separator + "IDX");
				if (!folder.exists()) {
					folder.mkdirs();
				}

				Map m = new HashMap();
				m.put("contextPath", ServerValue.getFrontContextPath());
				if (header != null) {
					m.put("head1", header.getOptions().get("tab1").getName());
					m.put("head2", header.getOptions().get("tab2").getName());
					m.put("head3", header.getOptions().get("tab3").getName());
				} else {
					m.put("head1", null);
					m.put("head2", null);
					m.put("head3", null);
				}

				for (int i = 0; i < 3; i++) {
					m.put("product1List", promote1.subList(i * 4, (i + 1) * 4 - 1));
					m.put("product2List", promote2.subList(i * 4, (i + 1) * 4 - 1));
					m.put("product3List", promote3.subList(i * 4, (i + 1) * 4 - 1));
					String fileData = templateService.format("static_Tab3_V2", m);
					File file = new File(ServerValue.getFrontContentHtmlPath() + File.separator + "IDX" + File.separator
							+ "IDX_RANKINGLIST_V2_" + (i + 1) + ".html");
					file.createNewFile();
					FileUtils.writeByteArrayToFile(file, fileData.getBytes());
				}
			} else {
				logger.warn("promote is empty, promote1:{},promote2:{},promote3:{}", new Object[] { promote1.size(),
						promote2.size(), promote3.size() });
			}

		} catch (IOException e) {
			logger.error("write file error", e);
			throw new CoreException("write file error", e);
		}
	}

	/**
	 * Index、館首頁黃金大看版
	 * 
	 * @param criteria
	 * @return
	 * @throws CoreException
	 */
	boolean generateMainGoldAdv(CommonCriteria criteria) throws CoreException {
		try {
			List<ViewPromotionAdvertise> viewPromotionAdvs = getViewPromotionAdvertiseDao().getList(criteria,
					new String[] { "startDate", "advTarget" });
			if (viewPromotionAdvs.size() > 0) {
				GenerateAdvertise advertise = null;
				String cateId = "";
				int k = 0;
				String[] tabProdId1 = new String[] { "tab1ProdId1", "tab2ProdId1", "tab3ProdId1", "tab4ProdId1", "tab5ProdId1" };
				String[] tabProdId2 = new String[] { "tab1ProdId2", "tab2ProdId2", "tab3ProdId2", "tab4ProdId2", "tab5ProdId2" };
				Map<String, Object> mainGoldMap = null;
				StringBuilder sbFilePath = null;
				Reader reader = null;
				Properties prop = null;
				List<ViewShelf> viewShelfList = null;
				Map<String, ViewShelf> shelfMap = null;
				Map<String, String> prodNameMap = null;

				ArrayList<String> tempProdIds = null;
				for (ViewPromotionAdvertise viewPromotionAdv : viewPromotionAdvs) {
					if (StringUtils.equalsIgnoreCase(viewPromotionAdv.getAdvType(), "100_MAINGOLD")) {
						cateId = viewPromotionAdv.getChildCateId().toString();
					} else if (StringUtils.equalsIgnoreCase(viewPromotionAdv.getAdvType(), "000_MAINGOLD")) {
						cateId = viewPromotionAdv.getMainCateId().toString();
					} else {
						cateId = "IDX";
					}

					mainGoldMap = new HashMap<String, Object>();
					shelfMap = new HashMap<String, ViewShelf>();
					prodNameMap = new HashMap<String, String>();
					sbFilePath = new StringBuilder();
					prop = new Properties();
					reader = new StringReader(viewPromotionAdv.getContents());
					prop.load(reader);
					reader.close();
					// 将各tab的prodId写到arraylist中
					tempProdIds = new ArrayList<String>();
					for (int i = 0; i < tabProdId1.length; i++) {
						if (StringUtils.isNotBlank(prop.getProperty(tabProdId1[i]))) {
							tempProdIds.add(prop.getProperty(tabProdId1[i]));
						}
						if (StringUtils.isNotBlank(prop.getProperty(tabProdId2[i]))) {
							tempProdIds.add(prop.getProperty(tabProdId2[i]));
						}
					}
					// 查询商品上架檔资讯
					if (tempProdIds.size() > 0) {
						viewShelfList = shelfService.getPublishShelfs(null, tempProdIds.toArray(new String[0]));
						if (!viewShelfList.isEmpty()) {
							for (ViewShelf vshelf : viewShelfList) {
								shelfMap.put(vshelf.getProductId(), vshelf);
								prodNameMap.put(vshelf.getProductId(), productDao.get(vshelf.getProductId()).getProductName());
							}
						}
					}
					mainGoldMap.put("prodNameMap", prodNameMap);
					mainGoldMap.put("prop", prop);
					mainGoldMap.put("shelfMap", shelfMap);
					mainGoldMap.put("advType", viewPromotionAdv.getAdvType());
					mainGoldMap.put("contentPath", ServerValue.getFrontContextPath());
					k++;
					boolean mkdirResult = mkGenerateHtmlDir(viewPromotionAdv.getAdvType(), cateId);
					if (mkdirResult) {
						sbFilePath.append(ServerValue.getFrontContentHtmlPath()).append(cateId).append(File.separator).append(
								viewPromotionAdv.getAdvType().split("_")[1]).append("_").append(k).append(subFileName);
						FileUtils.writeStringToFile(new File(sbFilePath.toString()), templateService.format("static_MainGold",
								mainGoldMap));
						sbFilePath.setLength(0);
						// update 廣告狀態為20(放送中-前3個才會被update)
						if (k <= 3) {
							advertise = getDao().get(Long.parseLong(String.valueOf(viewPromotionAdv.getId())));
							advertise.setAdvStatus("20");
							getDao().update(advertise);
						}
					}
				}
			}
		} catch (Exception e) {
			logger.error("generateMainGoldAdv exception:{}", e.fillInStackTrace());
			return false;
		}
		return true;
	}

	boolean generateMidBoxAdv_V2(CommonCriteria criteria, String vmName) throws CoreException {
		try {
			List<ViewPromotionAdvertise> viewPromotionAdvs = getViewPromotionAdvertiseDao().getList(criteria,
					new String[] { "startDate", "advTarget" });
			if (viewPromotionAdvs.size() > 0) {
				List<Long> updateList = new ArrayList<Long>();
				GenerateAdvertise advertise = null;
				Map<String, Object> midBoxMap = null;
				Map<String, Product> productMap = null;
				CommonCriteria prdtCriteria = null;
				String cateId = "";
				String advType = "";
				int k = 0, x = 1;
				int y = 1;
				int z = 1;
				String[] tempTabProdIds = new String[] { "tab1ProdId1", "tab1ProdId2", "tab1ProdId3", "tab2ProdId1",
						"tab2ProdId2", "tab2ProdId3", "tab3ProdId1", "tab3ProdId2", "tab3ProdId3", "tab4ProdId1", "tab4ProdId2",
						"tab4ProdId3" };
				StringBuilder sbFilePath = null;
				Reader reader = null;
				Properties prop = null;
				List<ViewShelf> viewShelfList = null;
				Map<String, ViewShelf> shelfMap = null;
				ArrayList<String> tempProdIds = new ArrayList<String>();
				for (ViewPromotionAdvertise viewPromotionAdv : viewPromotionAdvs) {
					tempProdIds.clear();
					midBoxMap = new HashMap<String, Object>();
					productMap = new HashMap<String, Product>();
					sbFilePath = new StringBuilder();
					prop = new Properties();
					reader = new StringReader(viewPromotionAdv.getContents());
					prop.load(reader);
					reader.close();
					// 将各tab的prodId写到arraylist中
					tempProdIds = new ArrayList<String>();
					for (int i = 0; i < tempTabProdIds.length; i++) {
						tempProdIds.add(prop.getProperty(tempTabProdIds[i]).toString());
					}

					// 查询商品上架檔资讯
					if (tempProdIds.size() > 0) {
						viewShelfList = shelfService.getPublishShelfs(null, tempProdIds.toArray(new String[0]));
						prdtCriteria = new CommonCriteria();
						prdtCriteria.addIn("productId", tempProdIds);
						productMap = productDao.getMap("productId", prdtCriteria, null);
						shelfMap = new HashMap<String, ViewShelf>();
						if (!viewShelfList.isEmpty()) {
							for (ViewShelf shelf : viewShelfList) {
								shelfMap.put(shelf.getProductId(), shelf);
							}
						}

						// 检核商品并寄发错误通知信
						generateNotifyService.sendNotificationForProductIdsWithProblem(Long.parseLong("0"), tempProdIds,
								viewPromotionAdv.getAdvType(), viewPromotionAdv.getAdvName());
					}

					midBoxMap.put("prop", prop);
					midBoxMap.put("shelfMap", shelfMap);
					midBoxMap.put("productMap", productMap);
					advType = viewPromotionAdv.getAdvType();
					midBoxMap.put("advType", viewPromotionAdv.getAdvType());
					midBoxMap.put("advTarget", viewPromotionAdv.getAdvTarget());
					midBoxMap.put("contentPath", ServerValue.getFrontContextPath());
					cateId = "IDX";
					if ("TOP".equalsIgnoreCase(viewPromotionAdv.getAdvTarget())) {
						k = x++;
					} else if ("MID".equalsIgnoreCase(viewPromotionAdv.getAdvTarget())) {
						k = y++;
					} else if ("BTM".equalsIgnoreCase(viewPromotionAdv.getAdvTarget())) {
						k = z++;
					}
					boolean mkdirResult = mkGenerateHtmlDir(viewPromotionAdv.getAdvType(), cateId);
					if (mkdirResult) {
						sbFilePath.append(ServerValue.getFrontContentHtmlPath()).append(cateId).append(File.separator).append(
								viewPromotionAdv.getAdvType()).append("_").append(viewPromotionAdv.getAdvTarget()).append("_")
								.append(k).append(subFileName);
						FileUtils.writeStringToFile(new File(sbFilePath.toString()), templateService.format(vmName, midBoxMap));
						sbFilePath.setLength(0);
						// update 廣告狀態為20(放送中-前3個才會被update)
						if (k <= 3) {
							updateList.add(Long.parseLong(String.valueOf(viewPromotionAdv.getId())));
							// advertise = getDao().get(Long.parseLong(String.valueOf(viewPromotionAdv.getId())));
							// advertise.setAdvStatus("20");
							// getDao().update(advertise);
						}
					}
				}
				if (updateList.size() > 0) {
					updateAdvStatus(advType, updateList);
				}
			}
		} catch (Exception e) {
			logger.error("generateMidBoxAdv exception:{}", e.fillInStackTrace());
			return false;
		}
		return true;
	}

	@Override
	public void generateNaviBar(String date) throws CoreException {
		try {
			List<Category> categories = categoryService.getAvailableCategory();

			for (Category cat : categories) {
				StringBuffer sb = new StringBuffer("<div class=\"location\"><a href=\"/\">首页</a> &gt; ");
				StringBuffer psb = new StringBuffer("<div class=\"location\"><a href=\"")
						.append(ServerValue.getFrontHostname()).append("\">首页</a> &gt; ");
				List<Object[]> catPath = categoryService.getCategoryLevelBottom(cat.getId());
				for (int i = 0; i < catPath.size(); i++) {
					Object[] ctry = catPath.get(i);
					if (i < catPath.size() - 1) {
						String catId = "";
						String catName = "";
						for (int j = 0; j < ctry.length; j++) {
							switch (j) {
							case 1:// category name
								catName = String.valueOf(ctry[j]).trim();
								break;
							case 3:// category id
								catId = String.valueOf(ctry[j]);
								break;
							}
						}
						sb.append("<a href=\"").append(ServerValue.getFrontContextPath()).append("/category/category.do?z=")
								.append(catId).append("\">").append(catName).append("</a> &gt; ");
						psb.append("<a href=\"").append(ServerValue.getFrontContextPath()).append("/category/category.do?z=")
								.append(catId).append("\">").append(catName).append("</a> &gt; ");
					} else {
						sb.append(" <span>").append(cat.getName()).append("</span>");
						psb.append("<a href=\"").append(ServerValue.getFrontContextPath()).append("/category/category.do?z=")
								.append(String.valueOf(ctry[3])).append("\">").append(String.valueOf(ctry[1]).trim()).append("</a>");
					}
				}
				sb.append("</div>");
				psb.append("</div>");

				// ServerValue.getFrontContentHtmlPath/#/@00_NAVIBAR.html
				StringBuffer naviBatFilePath = new StringBuffer(ServerValue.getFrontContentHtmlPath()).append(File.separator)
						.append(cat.getId()).append(File.separator).append("NAVIBAR.html");
				FileUtils.writeStringToFile(new File(naviBatFilePath.toString()), sb.toString());
				StringBuffer naviBatFilePath2 = new StringBuffer(ServerValue.getFrontContentHtmlPath()).append(File.separator)
						.append(cat.getId()).append(File.separator).append("PROD_NAVIBAR.html");
				FileUtils.writeStringToFile(new File(naviBatFilePath2.toString()), psb.toString());
			}
		} catch (Exception e) {
			logger.error("generateNaviBar.exception:{}", e.fillInStackTrace());
		}

	}

	@Override
	@Transactional(readOnly = false)
	public void updateAdvStatus(String adType, List<Long> idList) throws Exception {
		if (StringUtils.isBlank(adType)) {
			throw new Exception("广告类别未输入");
		}
		if (idList == null) {
			idList = new ArrayList<Long>();
		}
		if (idList.size() == 0) {
			idList.add(Long.parseLong("-1"));
		}
		Map<String, Object> attr = new HashMap<String, Object>();
		attr.put("type", adType);
		attr.put("idList", idList);

		// update 過期
		baseMgr
				.executeHql(
						"update generateAdvertise set advStatus ='80' where id not in (:idList) and sysdate >= endDate and advStatus in ('10','20') and advType =:type",
						attr);
		// update to 發送
		baseMgr
				.executeHql(
						"update generateAdvertise set advStatus ='10' where id not in (:idList) and advStatus in ('20') and sysdate between startDate and endDate and advType =:type",
						attr);
		// update to 發送中
		baseMgr.executeHql("update generateAdvertise set advStatus ='20' where id in (:idList)", attr);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.generate.service.GenerateService#generateRightDownAdvV2(java.lang.Long, java.lang.String)
	 */
	@Override
	@Transactional(readOnly = false)
	public void generateRightDownAdvV2(Long categoryId) throws CoreException, Exception {
		String[] advType = { "IDX_RDADV" };
		List<ViewPromotionAdvertise> viewPromotionAdvs = null;
		for (int i = 0; i < advType.length; i++) {
			java.util.Hashtable<String, String> countH = new java.util.Hashtable<String, String>();
			CommonCriteria criteria = new CommonCriteria();
			criteria.addEq("advType", advType[i]);
			// criteria.addEq("advTarget", advTarget);
			// 原先產生檔案的時候，如果分 advTarget，在 update adv status 的時候，會把另一種 advTarget 放送中的廣告 update 成發送
			// 所以現在產生的時候就不分 advTarge，把所有熱銷排行／最熱評價的廣告撈出來產生檔案，就不會有不該被 update 的廣告被 update
			criteria.addLe("startDate", new Date());
			criteria.addGe("endDate", new Date());
			if (categoryId != null && categoryId != 0) {
				criteria.addEq("mainCateId", categoryId);
			}
			viewPromotionAdvs = getViewPromotionAdvertiseDao().getList(criteria, null);

			if (viewPromotionAdvs.size() > 0) {
				List<Long> updateList = new ArrayList<Long>();
				Reader reader = null;
				Properties prop = null;
				for (ViewPromotionAdvertise viewPromotionAdv : viewPromotionAdvs) {
					String nowCat = viewPromotionAdv.getAdvType().equals("IDX_RDADV") ? "0" : (viewPromotionAdv.getAdvType()
							.equals("000_RDADV") ? Long.toString(viewPromotionAdv.getMainCateId()) : Long.toString(viewPromotionAdv
							.getChildCateId()));
					prop = new Properties();
					reader = new StringReader(viewPromotionAdv.getContents());
					prop.load(reader);
					reader.close();
					Map<String, Object> m = new HashMap<String, Object>();
					Map<String, String> prodNameMap = new HashMap<String, String>();
					Product p;
					List<String> productIdList = new ArrayList<String>();

					if (prop.containsKey("tab1ProdId")) {
						p = productDao.get(prop.getProperty("tab1ProdId"));
						prodNameMap.put(prop.getProperty("tab1ProdId"), null == p ? " " : p.getProductName());
						String productId = prop.getProperty("tab1ProdId");
						productIdList.add(productId);
					}
					if (prop.containsKey("tab2ProdId")) {
						p = productDao.get(prop.getProperty("tab2ProdId"));
						prodNameMap.put(prop.getProperty("tab2ProdId"), null == p ? " " : p.getProductName());
						String productId = prop.getProperty("tab2ProdId");
						productIdList.add(productId);
					}
					if (prop.containsKey("tab3ProdId")) {
						p = productDao.get(prop.getProperty("tab3ProdId"));
						prodNameMap.put(prop.getProperty("tab3ProdId"), null == p ? " " : p.getProductName());
						String productId = prop.getProperty("tab3ProdId");
						productIdList.add(productId);
					}
					m.put("contentPath", ServerValue.getFrontContextPath());
					m.put("prop", prop);
					m.put("advType", viewPromotionAdv.getAdvType());
					m.put("prodNameMap", prodNameMap);
					String htmlName;
					String countKey;
					if (viewPromotionAdv.getAdvTarget().equals("TOP")) {
						m.put("classType", "infoarea");
						htmlName = (nowCat.equals("0") ? "IDX_" : "") + "INFO_" + (nowCat.equals("0") ? "V2_" : "");
						countKey = nowCat + "TOP";
					} else {
						m.put("classType", "broadcast");
						htmlName = (nowCat.equals("0") ? "IDX_" : "") + "BROADCAST_" + (nowCat.equals("0") ? "V2_" : "");
						countKey = nowCat + "BTM";
					}

					String count;
					if (countH.containsKey(countKey)) {
						count = Integer.toString((Integer.parseInt(countH.get(countKey).toString()) + 1));
						countH.put(countKey, count);
					} else {
						deleteFiles(ServerValue.getFrontContentHtmlPath() + (nowCat.equals("0") ? "IDX" : nowCat), htmlName);
						String htmlNameV3 = htmlName.replace('2', '3');
						deleteFiles(ServerValue.getFrontContentHtmlPath() + (nowCat.equals("0") ? "IDX" : nowCat), htmlNameV3);
						count = "1";
						countH.put(countKey, "1");
					}

					FileUtils.writeStringToFile(new File(ServerValue.getFrontContentHtmlPath()
							+ (nowCat.equals("0") ? "IDX" : nowCat) + File.separator + htmlName + count + ".html"), templateService
							.format(nowCat.equals("0") ? "static_RightDownAdv_V2" : "static_RightDownAdv", m));
					FileUtils.writeStringToFile(new File(ServerValue.getFrontContentHtmlPath() + "IDX" + File.separator
							+ htmlName.replace('2', '3') + count + ".html"), templateService.format("static_RightDownAdv_V3", m));
					updateList.add(Long.parseLong(String.valueOf(viewPromotionAdv.getId())));
					// GenerateAdvertise advertise = getDao().get(Long.parseLong(String.valueOf(viewPromotionAdv.getId())));
					// advertise.setAdvStatus("20");
					// getDao().update(advertise);

					// 检核商品并寄发错误通知信
					generateNotifyService.sendNotificationForProductIdsWithProblem(viewPromotionAdv.getMainCateId(),
							productIdList, viewPromotionAdv.getAdvType(), viewPromotionAdv.getAdvName());
				}
				if (updateList.size() > 0) {
					updateAdvStatus(advType[0], updateList);
				}
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.generate.service.GenerateService#generateSearchbar_V2(java.lang.String)
	 */
	@Override
	public void generateSearchbar_V2(String categoryId) throws CoreException {
		// 若 categoryId 為 0; 放到 IDX 目錄
		String pathId = "0".equals(categoryId) ? "IDX" : categoryId;
		try {
			CommonCriteria criteria = new CommonCriteria();
			criteria.addEq("categoryId", Long.valueOf(categoryId));
			List<Keyword> l = keywordService.getList(0, 1, criteria, null);
			Keyword tmp = (l != null && l.size() > 0) ? l.get(0) : null;
			if (tmp == null) {
				throw new CoreException("keyword is null, categoryId:" + categoryId);
			}
			Date currentDate = new Date();
			Map m = new HashMap();
			CommonCriteria cri = new CommonCriteria();
			cri.addEq("level", "0");
			cri.addEq("isDelete", "N");
			cri.addEq("isVisible", "Y");
			cri.addLe("startDate", currentDate);
			cri.addGe("endDate", currentDate);
			List tmpCategories = categoryService.getList(0, -1, cri, new String[] { "showSeq asc" });
			Category root = new Category();
			root.setId(0L);
			root.setName("全站");
			root.setShowSeq(0);
			tmpCategories.add(0, root);

			Object[] kds = baseMgr.queryByHql("from KeywordDefault where categoryId=?", new Object[] { Long
					.valueOf(categoryId) }, 0, 1);
			String cateLevel = "-1";
			if (!categoryId.equals("0")) {
				Category category = (Category) baseMgr.get(Category.class, Long.valueOf(categoryId));
				cateLevel = category.getLevel();
			}
			// Map encodeKeywords = new HashMap();
			// for (String word : tmp.getWords()) {
			// encodeKeywords.put(word, URLEncoder.encode(word, "UTF-8"));
			// }
			m.put("cateLevel", cateLevel);
			if (kds != null && kds.length > 0) {
				m.put("kd", ((KeywordDefault) kds[0]).getKeyword());
			} else {
				m.put("kd", "");
			}
			m.put("categoryId", categoryId);
			m.put("categories", tmpCategories);
			m.put("keywordObj", tmp);
			m.put("categoryL1Id", Long.valueOf(StringUtils.split(tmp.getCategoryPath(), "/")[0]));
			m.put("keywords", tmp.getWords());
			// m.put("encodeKeywords", encodeKeywords);
			m.put("contextPath", ServerValue.getFrontContextPath());

			String fileData = templateService.format("static_Searchbar_V2", m);
			File folder = new File(ServerValue.getFrontContentHtmlPath() + File.separator + pathId);
			if (!folder.exists()) {
				folder.mkdirs();
			}
			File file = new File(ServerValue.getFrontContentHtmlPath() + File.separator + pathId + File.separator
					+ "SEARCHBAR_V2.html");
			file.createNewFile();
			FileUtils.writeByteArrayToFile(file, fileData.getBytes());
			if ("IDX".equals(pathId)) {
				fileData = templateService.format("static_Idx_Searchbar_V2", m);
				folder = new File(ServerValue.getFrontContentHtmlPath() + File.separator + pathId);
				if (!folder.exists()) {
					folder.mkdirs();
				}
				file = new File(ServerValue.getFrontContentHtmlPath() + File.separator + pathId + File.separator
						+ "IDX_SEARCHBAR_V2.html");
				file.createNewFile();
				FileUtils.writeByteArrayToFile(file, fileData.getBytes());
			}
		} catch (Exception e) {
			logger.error("build file error, path:" + pathId, e);
		}
	}

	StringBuffer generateSidebarAfterSecondLevel(Category genThisCategory, boolean isEndNode, Long endNodeId)
			throws CoreException {
		StringBuffer sb = new StringBuffer();
		List<Category> sameLevelCategories = categoryService.getAvailableSameLevelCategory(genThisCategory.getParentId(),
				genThisCategory.getLevel());
		StringBuffer activitySb = new StringBuffer("<p>活动特辑</p><ul class=\"sdbar-sub\">\n");
		StringBuffer prodCategorySb = new StringBuffer("<p>商品分类</p><ul class=\"sdbar-sub\">\n");
		boolean isActivityAvailable = false;
		StringBuffer thisCategory = new StringBuffer();
		StringBuffer otherCategory = new StringBuffer();

		for (Category sameLevelCat : sameLevelCategories) {
			if ("Y".equals(sameLevelCat.getIsPromotion().trim())) {// 活动特辑
				isActivityAvailable = true;
				List<Category> subCategories = categoryService.getAvailableChild(sameLevelCat.getId());

				String secondCategoryString = subCategories.size() > 0 ? "getmore" : "";// 有第二層
				String highlightString = "Y".equals(sameLevelCat.getIsHighlight()) ? "a-red" : "";// 有強調

				activitySb.append("<li><a href=\"").append(ServerValue.getFrontContextPath())
						.append("/category/category.do?z=").append(sameLevelCat.getId()).append("\" class=\"").append(
								highlightString).append(" ").append(secondCategoryString).append("\">").append(sameLevelCat.getName())
						.append("</a>\n");

				// 第二層隱藏目錄
				if (subCategories.size() > 0) {
					activitySb.append("<ul class=\"moreshow\" style=\"display:none;\">");
					for (Category secondSubCat : subCategories) {

						activitySb.append("<li> <a href=\"").append(ServerValue.getFrontContextPath()).append(
								"/category/category.do?z=").append(secondSubCat.getId()).append("\">").append(secondSubCat.getName())
								.append("</a></li> ");
					}
					activitySb.append("</ul>\n");
				}
				activitySb.append("</li>\n");
			} else {// 商品分类
				List<Category> subCategories = categoryService.getAvailableChild(sameLevelCat.getId());

				if (genThisCategory.getId() == sameLevelCat.getId()) {// 選中的目錄
					thisCategory.append("<li").append(isEndNode ? " class=\"limenu\"" : " class=\"limenu-f\"").append(">")
							.append(sameLevelCat.getName()).append("</li>\n");

					// 第二層條列目錄
					if (subCategories.size() > 0) {
						thisCategory.append("<ul class=\"show-dtl\">");
						for (Category secondSubCat : subCategories) {

							// endNode 的處理
							String endNodeSelectStr = "";
							if (isEndNode && secondSubCat.getId() == endNodeId) {
								endNodeSelectStr = " class=\"li-L4-f\"";
							}
							if ("Y".equals(secondSubCat.getIsPromotion().trim())) {// 活动特辑
								isActivityAvailable = true;
								String highlightString = "Y".equals(secondSubCat.getIsHighlight()) ? "a-red" : "";// 有強調

								activitySb.append("<li").append(endNodeSelectStr).append("><a href=\"").append(
										ServerValue.getFrontContextPath()).append("/category/category.do?z=").append(secondSubCat.getId())
										.append("\" class=\"").append(highlightString).append("\">").append(secondSubCat.getName()).append(
												"</a>\n");

							} else {

								thisCategory.append("<li").append(endNodeSelectStr).append("> <a href=\"").append(
										ServerValue.getFrontContextPath()).append("/category/category.do?z=").append(secondSubCat.getId())
										.append("\">").append(secondSubCat.getName()).append("</a></li> ");

							}
						}
						thisCategory.append("</ul>\n");
					}
				} else {// 同層其他的目錄
					String secondCategoryString = subCategories.size() > 0 ? "getmore" : "";// 有第二層
					String highlightString = "Y".equals(sameLevelCat.getIsHighlight()) ? "a-red" : "";// 有強調

					otherCategory.append("<li><a href=\"").append(ServerValue.getFrontContextPath()).append(
							"/category/category.do?z=").append(sameLevelCat.getId()).append("\" class=\"").append(highlightString)
							.append(" ").append(secondCategoryString).append("\">").append(sameLevelCat.getName()).append("</a>\n");

					// 第二層隱藏目錄
					if (subCategories.size() > 0) {
						otherCategory.append("<ul class=\"moreshow\" style=\"display:none;\">");
						for (Category secondSubCat : subCategories) {

							otherCategory.append("<li> <a href=\"").append(ServerValue.getFrontContextPath()).append(
									"/category/category.do?z=").append(secondSubCat.getId()).append("\">").append(secondSubCat.getName())
									.append("</a></li> ");

						}
						otherCategory.append("</ul>\n");
					}
					otherCategory.append("</li>\n");
				}

			}
		}
		prodCategorySb.append(thisCategory).append(otherCategory);

		if (isActivityAvailable) {
			sb.append(activitySb).append("</ul>");
		}
		sb.append(prodCategorySb);

		sb.append("</ul>");
		return sb;
	}

	void generateSidebarAfterSecondLevel2(Category nowCat, Category genThisCategory, Map<String, Object> sidebarMap)
			throws CoreException {
		sidebarMap.put("genThisCategory", genThisCategory);
		List<Category> sameLevelCategories = categoryService.getAvailableSameLevelCategory(genThisCategory.getParentId(),
				genThisCategory.getLevel());
		List<Category> subCategoriesNormal = new ArrayList<Category>();
		Hashtable<Long, List<Category>> catHNormal = new Hashtable<Long, List<Category>>();
		List<Category> subCategoriesPromote = new ArrayList<Category>();
		List<Category> subCategoriesBrand = new ArrayList<Category>();
		Hashtable<Long, List<Category>> empty = new Hashtable<Long, List<Category>>();

		for (Category sameLevelCat : sameLevelCategories) {
			// 商品分类
			if (("N".equals(sameLevelCat.getIsBrand().trim()) && "N".equals(sameLevelCat.getIsPromotion().trim()))
					|| (nowCat.getParentId().equals(sameLevelCat.getId()) || sameLevelCat.getId().equals(nowCat.getId()))) {
				subCategoriesNormal.add(sameLevelCat);
			}
			List<Category> subCategories = categoryService.getVisibleChild(sameLevelCat.getId());
			List<Category> tmpCategories = new ArrayList<Category>();
			for (Category nextLevelCat : subCategories) {
				if (nowCat.getParentId().equals(sameLevelCat.getId()) || sameLevelCat.getId().equals(nowCat.getId())) {
					if ("Y".equals(nextLevelCat.getIsPromotion().trim())) {// 活动特辑
						subCategoriesPromote.add(nextLevelCat);
					}
					if ("Y".equals(nextLevelCat.getIsBrand().trim())) {// 品牌分类
						subCategoriesBrand.add(nextLevelCat);
					}
				}
				if ("N".equals(nextLevelCat.getIsBrand().trim()) && "N".equals(nextLevelCat.getIsPromotion().trim())) {
					tmpCategories.add(nextLevelCat);
				}
			}
			catHNormal.put(sameLevelCat.getId(), tmpCategories);
		}
		sidebarMap.put("subCategoriesPromote", subCategoriesPromote);
		sidebarMap.put("empty", empty);
		sidebarMap.put("subCategoriesBrand", subCategoriesBrand);
		sidebarMap.put("subCategoriesNormal", subCategoriesNormal);
		sidebarMap.put("catHNormal", catHNormal);
	}

	@Override
	public void generateSideBarMenu(String date) throws CoreException {
		try {
			List<Category> categories = categoryService.getAvailableCategory();

			for (Category cat : categories) {
				String catLevel = StringUtils.defaultString(cat.getLevel(), "0").trim();
				String allProdURL = "";
				if ("0".equals(catLevel) || "1".equals(catLevel)) {
					allProdURL = "<a href=\"" + ServerValue.getFrontContextPath() + "/category/categoryAll.do?z=" + cat.getId()
							+ "\">看全部</a>";

				}
				StringBuffer sb = new StringBuffer("<div class=\"ca-index-menu\"><h1>").append(allProdURL).append("<b>")
						.append(cat.getName()).append("</b></h1>");

				String catName = cat.getName().trim();
				Long catId = cat.getId();
				String catIsEndNode = cat.getIsEndnode().trim();
				String catIsActivity = cat.getIsPromotion();

				if ("Y".equals(catIsEndNode)) {// 底層
					Long catParentId = cat.getParentId();
					Category endNodeCategory = categoryService.getCategoryById(catParentId);

					sb.append(generateSidebarAfterSecondLevel(endNodeCategory, true, cat.getId()));

				} else if ("0".equals(catLevel)) {// 館首頁

					// 子目錄一
					List<Category> subCategories = categoryService.getAvailableChild(catId);
					sb.append("<ul class=\"sdbar-index\">");
					for (Iterator<Category> it = subCategories.iterator(); it.hasNext();) {
						Category subCat = it.next();
						if (!it.hasNext()) {
							sb.append("<li class=\"lastno\"><strong><a href=\"").append(ServerValue.getFrontContextPath()).append(
									"/category/category.do?z=").append(subCat.getId()).append("\">").append(subCat.getName()).append(
									"</a></strong><br>");
						} else {
							sb.append("<li><strong><a href=\"").append(ServerValue.getFrontContextPath()).append(
									"/category/category.do?z=").append(subCat.getId()).append("\">").append(subCat.getName()).append(
									"</a></strong><br>");
						}

						// 子目錄二
						List<Category> secondSubCategories = categoryService.getAvailableChild(subCat.getId());
						StringBuffer subCatStr = new StringBuffer();
						for (Category secondSubCat : secondSubCategories) {
							subCatStr.append("| <a href=\"").append(ServerValue.getFrontContextPath()).append(
									"/category/category.do?z=").append(secondSubCat.getId()).append("\">").append(
									secondSubCat.getAliasName()).append("</a> ");
						}
						if (secondSubCategories.size() > 0) {
							sb.append(subCatStr.substring(1).toString());
						}

						sb.append("</li>");
					}
					sb.append("</ul>");

				} else {// 中間層數
					sb.append(generateSidebarAfterSecondLevel(cat, false, Long.parseLong("0")));
				}

				sb.append("<img src=\"/images/none.gif\" alt=\"\" width=\"170\" height=\"14\" class=\"sidebar-ft\" /></div>");

				// ServerValue.getFrontContentHtmlPath/#/SIDEBAR.html
				StringBuffer naviBatFilePath = new StringBuffer(ServerValue.getFrontContentHtmlPath()).append(File.separator)
						.append(cat.getId()).append(File.separator).append("SIDEBAR.html");
				FileUtils.writeStringToFile(new File(naviBatFilePath.toString()), sb.toString());
			}
		} catch (Exception e) {
			logger.error("generateSideBarMenu.exception:{}", e.fillInStackTrace());
		}
	}

	@Override
	public void generateSideBarMenu2(String date) throws CoreException {
		try {
			List<Category> categories = categoryService.getAvailableCategory();

			for (Category cat : categories) {
				Map<String, Object> sidebarMap = new HashMap<String, Object>();
				sidebarMap.put("contentPath", ServerValue.getFrontContextPath());
				String catLevel = StringUtils.defaultString(cat.getLevel(), "0").trim();
				sidebarMap.put("category", cat);

				Long catId = cat.getId();
				String catIsEndNode = cat.getIsEndnode().trim();

				if ("Y".equals(catIsEndNode)) { // 底層
					generateSidebarAfterSecondLevel2(cat, categoryService.getCategoryById(cat.getParentId()), sidebarMap);
					StringBuffer naviBatFilePath = new StringBuffer(ServerValue.getFrontContentHtmlPath()).append(File.separator)
							.append(cat.getId()).append(File.separator).append("SIDEBAR.html");
					FileUtils.writeStringToFile(new File(naviBatFilePath.toString()), templateService.format(
							"static_sidebar_lv2", sidebarMap));
					sidebarMap.put("isProduct", "Y");
					generateSidebarAfterSecondLevel2(cat, categoryService.getCategoryById(cat.getParentId()), sidebarMap);
					naviBatFilePath = new StringBuffer(ServerValue.getFrontContentHtmlPath()).append(File.separator).append(
							cat.getId()).append(File.separator).append("SIDEBAR_P.html");
					FileUtils.writeStringToFile(new File(naviBatFilePath.toString()), templateService.format(
							"static_sidebar_lv2", sidebarMap));
				} else if ("0".equals(catLevel)) {// 館首頁

					// 子目錄一
					List<Category> subCategories = categoryService.getVisibleChild(catId);
					List<Category> tmpCategories = new ArrayList<Category>();
					for (Category subCat : subCategories) {
						if ("N".equals(subCat.getIsBrand().trim()) && "N".equals(subCat.getIsPromotion().trim())) {
							tmpCategories.add(subCat);
						}
					}
					sidebarMap.put("subCategories", tmpCategories);

					Hashtable<Long, List<Category>> catH = new Hashtable<Long, List<Category>>();
					for (Iterator<Category> it = subCategories.iterator(); it.hasNext();) {
						Category subCat = it.next();

						// 子目錄二
						List<Category> secondSubCategories = categoryService.getVisibleChild(subCat.getId());
						tmpCategories = new ArrayList<Category>();
						for (Category nextLevelCat : secondSubCategories) {
							if ("N".equals(nextLevelCat.getIsBrand().trim()) && "N".equals(nextLevelCat.getIsPromotion().trim())) {
								tmpCategories.add(nextLevelCat);
							}
						}
						catH.put(subCat.getId(), tmpCategories);
					}
					sidebarMap.put("catH", catH);
					StringBuffer naviBatFilePath = new StringBuffer(ServerValue.getFrontContentHtmlPath()).append(File.separator)
							.append(cat.getId()).append(File.separator).append("SIDEBAR.html");
					FileUtils.writeStringToFile(new File(naviBatFilePath.toString()), templateService.format(
							"static_sidebar_lv1", sidebarMap));
				} else {
					generateSidebarAfterSecondLevel2(cat, cat, sidebarMap);
					StringBuffer naviBatFilePath = new StringBuffer(ServerValue.getFrontContentHtmlPath()).append(File.separator)
							.append(cat.getId()).append(File.separator).append("SIDEBAR.html");
					FileUtils.writeStringToFile(new File(naviBatFilePath.toString()), templateService.format(
							"static_sidebar_lv2", sidebarMap));
				}
			}
		} catch (Exception e) {
			logger.error("generateSideBarMenu.exception:{}", e.fillInStackTrace());
		}
	}

	@Override
	@Transactional(readOnly = false)
	public boolean generateSpecialAct(Long categoryId) throws CoreException, IOException {
		List<ViewPromotionAdvertise> viewPromotionAdvs = null;
		List<Category> categories = null;

		if (categoryId != null && categoryId != 0) {
			categories = new ArrayList<Category>();
			categories.add(categoryService.getCategoryById(categoryId));
		} else {
			categories = categoryService.getAvailableSameLevelCategory(Long.parseLong("0"), "0");
		}

		for (Category category : categories) {
			// 刪除原本的檔案
			File file = new File(ServerValue.getFrontContentHtmlPath() + category.getId() + File.separator
					+ "SPECIALACT.html.html");
			if (file.exists()) {
				FileUtils.forceDelete(file);
			}
			CommonCriteria criteria = new CommonCriteria();
			criteria.addEq("advType", "000_SPECIALACT");
			criteria.addEq("mainCateId", category.getId());
			criteria.addLe("startDate", new Date());
			criteria.addGe("endDate", new Date());
			String nowCat = category.getId().toString();
			viewPromotionAdvs = getViewPromotionAdvertiseDao().getList(criteria,
					new String[] { "showSeq asc", "modifyDate desc" });
			if (viewPromotionAdvs.size() > 0) {
				Reader reader = null;
				Properties prop = null;
				Map<String, Object> m = new HashMap<String, Object>();
				List<Properties> bannerList = new ArrayList<Properties>();
				List<Properties> normalList = new ArrayList<Properties>();
				List<String> productIdList = new ArrayList<String>();
				for (int j = viewPromotionAdvs.size() - 1; j >= 0; j--) {
					ViewPromotionAdvertise viewPromotionAdv = viewPromotionAdvs.get(j);
					GenerateAdvertise advertise = getDao().get(Long.parseLong(String.valueOf(viewPromotionAdv.getId())));
					if (j < 10) {
						prop = new Properties();
						reader = new StringReader(viewPromotionAdv.getContents());
						prop.load(reader);
						reader.close();

						Product p;
						Shelf s;
						String pid;
						for (int i = 1; i <= 8; i++) {
							if (prop.containsKey("tab" + i + "ProdId")) {
								pid = prop.getProperty("tab" + i + "ProdId");
								p = productDao.get(pid);
								s = shelfService.getActiveShelfByProductId(pid);
								if (null != p && null != s) {
									prop.setProperty("tab" + i + "ListPrice", p.getListPrice().toString());
									prop.setProperty("tab" + i + "IsSoldOut", p.getIsSoldOut().toString());
									prop.setProperty("tab" + i + "ShelfPrice", s.getShelfPrice().toString());
								} else {
									productIdList.add(pid);
								}
							}
						}
						if (prop.containsKey("bannerImgName")) {
							bannerList.add(prop);
						} else {
							normalList.add(prop);
						}
						advertise.setAdvStatus("20");
						getDao().update(advertise);
					} else {
						advertise.setAdvStatus("10");
						getDao().update(advertise);
					}
					m.put("categoryId", categoryId);
					m.put("showSeq", viewPromotionAdv.getShowSeq());

					// 检核商品并寄发错误通知信
					generateNotifyService.sendNotificationForProductIdsWithProblem(category.getId(), productIdList,
							viewPromotionAdv.getAdvType(), viewPromotionAdv.getAdvName());

					productIdList.clear();
				}
				Collections.reverse(bannerList);
				Collections.reverse(normalList);
				m.put("contentPath", ServerValue.getFrontContextPath());
				m.put("advType", "000_SPECIALACT");
				m.put("bannerList", bannerList);
				m.put("normalList", normalList);
				FileUtils.writeStringToFile(new File(ServerValue.getFrontContentHtmlPath() + nowCat + File.separator
						+ "SPECIALACT.html"), templateService.format("static_SpecialAct", m));
			}
		}
		return true;
	}

	@Override
	public void generateCategoryTopRank(String categoryIdString) throws CoreException, IOException {
		List<Category> categoryList = null;

		if (categoryIdString == null || StringUtils.trim(categoryIdString).equals("0")) {
			// 產生所有類別的排行
			categoryList = categoryService.getAvailableCategory();
		} else {
			// 產生一個類別的排行
			if (!StringUtils.isNumeric(categoryIdString)) {
				return;
			}
			Category onlyOne = categoryService.get(Long.parseLong(categoryIdString));
			categoryList = new ArrayList<Category>();
			if (onlyOne == null) {
				return;
			}
			categoryList.add(onlyOne);
		}

		for (Category category : categoryList) {
			HashMap<String, Object> parameterMap = new HashMap<String, Object>();
			List<ViewReportProductClick> categoryRank = viewReportProductClickService.getTopRank(category.getId().toString());
			String currentCategoryIdString = category.getId().toString();

			parameterMap.put("categoryRank", categoryRank);
			parameterMap.put("contextPath", ServerValue.getFrontContextPath());

			String filePath = ServerValue.getFrontContentHtmlPath() + currentCategoryIdString + File.separator
					+ "CATEGORY_PRODUCT_RANK.html";
			FileUtils.writeStringToFile(new File(filePath), templateService.format("static_CategoryTopRank", parameterMap));
		}
	}

	public AnnouncementService getAnnouncementService() {
		return announcementService;
	}

	public CategoryService getCategoryService() {
		return categoryService;
	}

	public ObjectDao<EventImage> getEventImageDao() {
		return eventImageDao;
	}

	public MailService getMailService() {
		return this.mailService;
	}

	public UserService getUserService() {
		return this.userService;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.generate.service.GenerateService#getGenerateAdvertiseList(int, int,
	 * com.yaodian100.core.common.dao.impl.CommonCriteria, java.lang.String[])
	 */
	@Override
	public List<GenerateAdvertise> getGenerateAdvertiseList(int firstResult, int maxResults, CommonCriteria criteria,
			String[] sortOrder) throws CoreException {
		List<GenerateAdvertise> generateAdvertise = getDao().getListPageable(criteria, sortOrder, firstResult, maxResults);
		return generateAdvertise;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.yaodian100.ec.generate.service.GenerateService#getGenerateAdvertiseSize(com.yaodian100.core.common.dao.impl
	 * .CommonCriteria)
	 */
	@Override
	public Number getGenerateAdvertiseSize(CommonCriteria criteria) throws CoreException {
		return getDao().getListSize(criteria);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.generate.service.GenerateService#getGenerateContentByAdvId(int)
	 */
	@Override
	public List<GenerateContent> getGenerateContentByAdvId(Long advId) throws CoreException {
		CommonCriteria criteria = new CommonCriteria();
		criteria.addEq("advId", advId);
		return getGenerateContentDao().getList(criteria, null);
	}

	public ObjectDao<GenerateContent> getGenerateContentDao() {
		return generateContentDao;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seecom.yaodian100.ec.generate.service.GenerateService#getGenerateContentList(com.yaodian100.core.common.dao.impl.
	 * CommonCriteria)
	 */
	@Override
	public List<GenerateContent> getGenerateContentList(CommonCriteria criteria) throws CoreException {
		return getGenerateContentDao().getList(criteria, null);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.generate.service.GenerateService#getGeneratePositionByAdvId(int)
	 */
	@Override
	public List<GeneratePosition> getGeneratePositionByAdvId(Long advId) throws CoreException {
		CommonCriteria criteria = new CommonCriteria();
		criteria.addEq("advId", advId);
		return getGeneratePositionDao().getList(criteria, null);
	}

	public ObjectDao<GeneratePosition> getGeneratePositionDao() {
		return generatePositionDao;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.yaodian100.ec.generate.service.GenerateService#getGeneratePositionList(com.yaodian100.core.common.dao.impl.
	 * CommonCriteria)
	 */
	@Override
	public List<GeneratePosition> getGeneratePositionList(CommonCriteria criteria) throws CoreException {
		return getGeneratePositionDao().getList(criteria, null);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.yaodian100.ec.generate.service.GenerateService#getGeneratePositionSize(com.yaodian100.core.common.dao.impl.
	 * CommonCriteria)
	 */
	@Override
	public Number getGeneratePositionSize(CommonCriteria criteria) throws CoreException {
		return getGeneratePositionDao().getListSize(criteria);
	}

	public ObjectDao<Product> getProductDao() {
		return productDao;
	}

	public ShelfService getShelfService() {
		return shelfService;
	}

	public ObjectDao<ViewPmAdvertise> getViewPmAdvertiseDao() {
		return viewPmAdvertiseDao;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.generate.service.GenerateService#getViewPmAdvertiseList(int, int,
	 * com.yaodian100.core.common.dao.impl.CommonCriteria, java.lang.String[])
	 */
	@Override
	public List<ViewPmAdvertise> getViewPmAdvertiseList(int firstResult, int maxResults, CommonCriteria criteria,
			String[] sortOrder) throws CoreException {
		criteria = addPermissionCrit(criteria);// 分線維護權限檢核
		return viewPmAdvertiseDao.getListPageable(criteria, sortOrder, firstResult, maxResults);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seecom.yaodian100.ec.generate.service.GenerateService#getViewPmAdvertiseSize(com.yaodian100.core.common.dao.impl.
	 * CommonCriteria)
	 */
	@Override
	public Number getViewPmAdvertiseSize(CommonCriteria criteria) throws CoreException {
		criteria = addPermissionCrit(criteria);// 分線維護權限檢核
		return viewPmAdvertiseDao.getListSize(criteria);
	}

	public ObjectDao<ViewPromotionAdvertise> getViewPromotionAdvertiseDao() {
		return viewPromotionAdvertiseDao;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.yaodian100.ec.generate.service.GenerateService#getViewGenerateAdvertiseList(int, int,
	 * com.yaodian100.core.common.dao.impl.CommonCriteria, java.lang.String[])
	 */
	@Override
	public List<ViewPromotionAdvertise> getViewPromotionAdvertiseList(int firstResult, int maxResults,
			CommonCriteria criteria, String[] sortOrder) throws CoreException {
		return getViewPromotionAdvertiseDao().getListPageable(criteria, sortOrder, firstResult, maxResults);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.yaodian100.ec.generate.service.GenerateService#getViewGenerateAdvertiseSize(com.yaodian100.core.common.dao.
	 * impl.CommonCriteria)
	 */
	@Override
	public Number getViewPromotionAdvertiseSize(CommonCriteria criteria) throws CoreException {
		return getViewPromotionAdvertiseDao().getListSize(criteria);
	}

	@Override
	public boolean isProductExist(String productId) {
		Product p = productDao.get(productId);
		if (null != p) {
			if (p.getProductType() == 2 || p.getProductType() == 3 || p.getIsDelete().equals("Y")
					|| (!p.getProductStatus().equals("PRD500")) || null == shelfService.getActiveShelfByProductId(productId)) {
				return false;
			}
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 建目錄
	 * 
	 * @param advType
	 * @param categoryId
	 * @return
	 */
	boolean mkGenerateHtmlDir(String advType, String categoryId) {
		try {
			if (!new File(ServerValue.getFrontContentHtmlPath() + categoryId).exists()) {
				FileUtils.forceMkdir(new File(ServerValue.getFrontContentHtmlPath() + categoryId));
			}
		} catch (IOException e) {
			logger.error("mkGenerateHtmlDir exception:{}", e.fillInStackTrace());
			return false;
		}
		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.yaodian100.ec.generate.service.GenerateService#saveEventImage(com.yaodian100.ec.generate.entity.EventImage)
	 */
	@Override
	@Transactional(readOnly = false)
	public EventImage saveEventImage(EventImage eventImage) throws CoreException {
		return getEventImageDao().save(eventImage);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seecom.yaodian100.ec.generate.service.GenerateService#saveGenerateAdvertise(com.yaodian100.ec.generate.entity.
	 * GenerateAdvertise)
	 */
	@Override
	@Transactional(readOnly = false)
	public GenerateAdvertise saveGenerateAdvertise(GenerateAdvertise generateAdvertise) throws CoreException {
		generateAdvertise = getDao().save(generateAdvertise);
		return generateAdvertise;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seecom.yaodian100.ec.generate.service.GenerateService#saveGenerateCombine(com.yaodian100.ec.generate.entity.
	 * GenerateAdvertise, com.yaodian100.ec.generate.entity.GeneratePosition,
	 * com.yaodian100.ec.generate.entity.GenerateContent)
	 */
	@Override
	@Transactional(readOnly = false)
	public boolean saveGenerateCombine(GenerateAdvertise generateAdvertise, GeneratePosition generatePosition,
			GenerateContent generateContent) throws CoreException {
		try {
			generateAdvertise = getDao().save(generateAdvertise);

			generatePosition.setAdvId(generateAdvertise.getId());
			generatePosition = getGeneratePositionDao().save(generatePosition);

			generateContent.setAdvId(generateAdvertise.getId());
			generateContent = getGenerateContentDao().save(generateContent);
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seecom.yaodian100.ec.generate.service.GenerateService#saveGenerateContent(com.yaodian100.ec.generate.entity.
	 * GenerateContent)
	 */
	@Override
	@Transactional(readOnly = false)
	public GenerateContent saveGenerateContent(GenerateContent generateContent) throws CoreException {
		generateContent = getGenerateContentDao().save(generateContent);
		return generateContent;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seecom.yaodian100.ec.generate.service.GenerateService#saveGeneratePosition(com.yaodian100.ec.generate.entity.
	 * GeneratePosition)
	 */
	@Override
	@Transactional(readOnly = false)
	public GeneratePosition saveGeneratePosition(GeneratePosition generatePosition) throws CoreException {
		generatePosition = getGeneratePositionDao().save(generatePosition);
		return generatePosition;
	}

	public void setAnnouncementService(AnnouncementService announcementService) {
		this.announcementService = announcementService;
	}

	public void setCategoryService(CategoryService categoryService) {
		this.categoryService = categoryService;
	}

	public void setEventImageDao(ObjectDao<EventImage> eventImageDao) {
		this.eventImageDao = eventImageDao;
	}

	public void setGenerateContentDao(ObjectDao<GenerateContent> generateContentDao) {
		this.generateContentDao = generateContentDao;
	}

	public void setGeneratePositionDao(ObjectDao<GeneratePosition> generatePositionDao) {
		this.generatePositionDao = generatePositionDao;
	}

	public void setProductDao(ObjectDao<Product> productDao) {
		this.productDao = productDao;
	}

	public void setShelfService(ShelfService shelfService) {
		this.shelfService = shelfService;
	}

	public void setViewPmAdvertiseDao(ObjectDao<ViewPmAdvertise> viewPmAdvertiseDao) {
		this.viewPmAdvertiseDao = viewPmAdvertiseDao;
	}

	public void setViewPromotionAdvertiseDao(ObjectDao<ViewPromotionAdvertise> viewPromotionAdvertiseDao) {
		this.viewPromotionAdvertiseDao = viewPromotionAdvertiseDao;
	}

	public void setMailService(MailService mailService) {
		this.mailService = mailService;
	}

	public void setUserService(UserService userService) {
		this.userService = userService;
	}

	public ViewReportProductClickService getViewReportProductClickService() {
		return this.viewReportProductClickService;
	}

	public void setViewReportProductClickService(ViewReportProductClickService viewReportProductClickService) {
		this.viewReportProductClickService = viewReportProductClickService;
	}

	public ProductService getProductService() {
		return this.productService;
	}

	public void setProductService(ProductService productService) {
		this.productService = productService;
	}

	public TemplateService getTemplateService() {
		return this.templateService;
	}

	public void setTemplateService(TemplateService templateService) {
		this.templateService = templateService;
	}

	public ProductRCService getProductRCService() {
		return productRCService;
	}

	public void setProductRCService(ProductRCService productRCService) {
		this.productRCService = productRCService;
	}

	public GenerateNotifyService getGenerateNotifyService() {
		return generateNotifyService;
	}

	public void setGenerateNotifyService(GenerateNotifyService generateNotifyService) {
		this.generateNotifyService = generateNotifyService;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seecom.yaodian100.ec.generate.service.GenerateService#updateGenerateAdvertise(com.yaodian100.ec.generate.entity.
	 * GenerateAdvertise)
	 */
	@Override
	@Transactional(readOnly = false)
	public GenerateAdvertise updateGenerateAdvertise(GenerateAdvertise generateAdvertise) throws CoreException {
		generateAdvertise = getDao().update(generateAdvertise);
		return generateAdvertise;
	}

	@Override
	@Transactional(readOnly = false)
	public boolean updateGenerateCombine(GenerateAdvertise generateAdvertise, GeneratePosition generatePosition,
			GenerateContent generateContent) throws CoreException {
		try {
			generateAdvertise = getDao().update(generateAdvertise);
			generatePosition = getGeneratePositionDao().update(generatePosition);
			generateContent = getGenerateContentDao().update(generateContent);
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seecom.yaodian100.ec.generate.service.GenerateService#updateGenerateContent(com.yaodian100.ec.generate.entity.
	 * GenerateContent)
	 */
	@Override
	@Transactional(readOnly = false)
	public GenerateContent updateGenerateContent(GenerateContent generateContent) throws CoreException {
		generateContent = getGenerateContentDao().update(generateContent);
		return generateContent;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seecom.yaodian100.ec.generate.service.GenerateService#updateGeneratePosition(com.yaodian100.ec.generate.entity.
	 * GeneratePosition)
	 */
	@Override
	@Transactional(readOnly = false)
	public GeneratePosition updateGeneratePosition(GeneratePosition generatePosition) throws CoreException {
		generatePosition = getGeneratePositionDao().update(generatePosition);
		return generatePosition;
	}

	@Override
	public boolean generateXMLforBaidu() {
		boolean isSuccessProductXML = generateProdXMLforBaidu();
		// boolean isSuccessProductXML = true;
		boolean isSuccessCategoryXML = generateCatXMLforBaidu();
		// boolean isSuccessCategoryXML = true;
		if (isSuccessProductXML && isSuccessCategoryXML) {
			return true;
		} else {
			return false;
		}

	}

	@Override
	public boolean generateXMLforFanli() {
		boolean isSuccessProductXML = generateProdXMLforFanli();

		if (isSuccessProductXML) {
			return true;
		} else {
			return false;
		}

	}

	/**
	 * @return
	 */
	private boolean generateProdXMLforFanli() {
		try {
			Date today = new Date();
			// 第一級和第二級的目錄，作為對照
			Map<String, String> catL1 = new HashMap<String, String>();
			Map<String, String> catL2 = new HashMap<String, String>();
			Map<String, String> catL3 = new HashMap<String, String>();
			CommonCriteria cc = new CommonCriteria();
			cc.addEq("isDelete", "N");
			cc.addLe("level", "3");
			cc.addLe("startDate", today);
			cc.addGe("endDate", today);
			List<Category> cats = categoryService.getList(0, -1, cc, new String[] { "level", "id" });
			for (Category cat : cats) {
				if ("0".equals(cat.getLevel())) {
					catL1.put(cat.getId().toString(), cat.getName());
				} else if ("1".equals(cat.getLevel())) {
					catL2.put(cat.getId().toString(), cat.getName());
				} else if ("2".equals(cat.getLevel())) {
					catL3.put(cat.getId().toString(), cat.getName());
				}

			}

			StringBuffer sql = new StringBuffer();
			sql.append(" select c.product_id, c.product_name, c.product_brief, a.shelf_price, ");
			sql.append("  b.img_file_path, a.category_path, D.BRAND_ENAME, D.BRAND_NAME  ");
			sql.append(" from ec_view_shelf_product a,  ");
			sql.append(" ec_image_main b, ec_product_main c, EC_BRAND_MAIN d  ");
			sql.append(" where a.product_id = c.product_id   ");
			sql.append(" and c.product_id = b.product_id   ");
			sql.append("  and c.PRODUCT_BRAND = d.brand_id ");
			sql.append(" and a.main_category_id in(  ");
			sql.append("   select category_id from ec_category_main   ");
			sql.append("   where is_delete = 'N'  ");
			sql.append("   and sysdate between start_date and end_date)  ");
			sql.append(" and a.main_category_id = substr(a.v_uk,  (InStr(a.v_uk,'_')) +1 )  ");
			sql.append(" and c.is_delete = 'N'  ");
			sql.append(" and b.image_type='MAIN'  ");
			sql.append(" and b.img_file_path like '%_m500.jpg'  ");
			sql.append(" and c.product_brief is not null  ");
			sql.append(" and c.PRODUCT_BRAND is not null  ");

			List<Map<String, Object>> shelfProducts = null;
			Document fenli = DocumentHelper.createDocument();
			Element productAll = fenli.addElement("product_all");
			// String catL1Id = it.next();
			shelfProducts = jdbcTemplate.queryForList(sql.toString());
			// 開始組合商品資料
			for (Iterator<Map<String, Object>> products = shelfProducts.iterator(); products.hasNext();) {
				Map<String, Object> pd = products.next();

				String productId = (String) pd.get("product_id");
				String productName = (String) pd.get("product_name");
				String productBrandE = (String) pd.get("BRAND_ENAME");
				String productBrandC = (String) pd.get("BRAND_NAME");
				BigDecimal shelfPrice = (BigDecimal) pd.get("shelf_price");
				// String productKeywords = StringUtils.replace((String) pd.get("product_keyword"), ",", "\\");
				String productBrief = (String) pd.get("product_brief");
				String[] productCategory = ((String) pd.get("category_path")).split("/");
				String productCategoryL1 = "";
				String productCategoryL2 = "";
				String productCategoryL3 = "";
				String productCategoryStr = "";
				if (productCategory.length > 1) {
					productCategoryL1 = catL1.containsKey(productCategory[0]) ? catL1.get(productCategory[0]) : "";
					productCategoryL2 = catL2.containsKey(productCategory[1]) ? catL2.get(productCategory[1]) : "";
					productCategoryStr = productCategoryL1 + ">" + productCategoryL2;
					if (productCategory.length > 2) {
						productCategoryL3 = catL3.containsKey(productCategory[2]) ? catL3.get(productCategory[2]) : "";
						productCategoryStr += ">" + productCategoryL3;
					}
				}

				String productImage = (String) pd.get("img_file_path");

				String productBrand = productBrandE + productBrandC;
				// 如果中英文同樣只取其一
				if (StringUtils.equals(StringUtils.trim(productBrandC), StringUtils.trim(productBrandE))) {
					productBrand = productBrandE;
				}

				Element product = productAll.addElement("product");
				// 有問題的資料跳過，eg.空白，null
				try {
					// 商品連結
					String productURL = ServerValue.getFrontHostname() + ServerValue.getFrontContextPath()
							+ "/product/product.do?hpp=51fanlixml&productId=" + productId;

					product.addElement("product_id").addText(productId);
					product.addElement("product_name").addText(productName);
					product.addElement("product_url").addText(productURL);
					product.addElement("product_des").addText(productBrief);
					product.addElement("price").addText(shelfPrice.toString());
					product.addElement("category").addText(productCategoryStr);
					product.addElement("brand").addText(productBrand);
					product.addElement("pic_url").addText(ServerValue.getImgDomain() + productImage);

				} catch (Exception e) {
					// 移除產生exception的node
					productAll.elements().remove(productAll.elements().size() - 1);
					logger.info(productId + "," + e.getMessage());
				}
			}
			File folder = new File(ServerValue.getMidApachePath() + "3party_ex" + File.separator + "51fanli"
					+ File.separatorChar);
			if (!folder.exists()) {
				folder.mkdirs();
			}

			File fanliXML = new File(ServerValue.getMidApachePath() + "3party_ex" + File.separator + "51fanli"
					+ File.separatorChar + "51fanli.xml");

			// 產生新檔案
			FileUtils.writeStringToFile(fanliXML, fenli.asXML(), "UTF-8");

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		return true;
	}

	private boolean generateCatXMLforBaidu() {
		try {
			Date today = new Date();
			// 現存目錄，作為對照
			Map<String, String> catAll = new HashMap<String, String>();
			CommonCriteria cc = new CommonCriteria();
			cc.addEq("isDelete", "N");
			cc.addLe("startDate", today);
			cc.addGe("endDate", today);
			List<Category> cats = categoryService.getList(0, -1, cc, new String[] { "level", "id" });
			for (Category cat : cats) {
				catAll.put(cat.getId().toString(), cat.getName());
			}
			// 公告兩則
			CommonCriteria criteria = new CommonCriteria();
			criteria.addEq("type", "MYYAODIAN");
			criteria.addEq("isDelete", "N");
			criteria.addLe("startDate", today);
			criteria.addGe("endDate", today);
			List<Announcement> newslist = announcementService.getList(0, 2, criteria, new String[] { "showSeq asc",
					"modifyDate desc" });
			boolean isPromotion1Exist = newslist.size() > 0 ? true : false;
			boolean isPromotion2Exist = newslist.size() > 1 ? true : false;

			ArrayList<String> baibuCatXMLNameList = new ArrayList<String>();

			StringBuffer sql = new StringBuffer();
			sql
					.append("select decode(nvl(b.brand_name,''),'',b.brand_ename,b.brand_name) as brand_name, a.main_category_id , a.category_path, sum(1) as pd_count ");
			sql.append("from ec_view_shelf_product a, ec_brand_main b, ec_product_main c ");
			sql.append("where a.product_id = c.product_id ");
			sql.append("and b.brand_id = c.product_brand ");
			sql.append("and a.main_category_id in (  ");
			sql.append("	select category_id  ");
			sql.append("	from ec_category_main  ");
			sql.append("	where is_delete = 'N'  ");
			sql.append("	and sysdate between start_date and end_date)  ");
			sql.append("and c.is_delete = 'N' ");
			sql.append("and b.brand_status = 'Y' ");
			sql.append("and a.main_category_id = substr(a.v_uk, (InStr(a.v_uk,'_')) +1 ) ");
			sql.append("and b.brand_id like 'BD%' ");
			sql
					.append("group by decode(nvl(b.brand_name,''),'',b.brand_ename,b.brand_name), a.main_category_id, a.category_path ");

			Document baidu = DocumentHelper.createDocument();
			Element urlset = baidu.addElement("urlset");

			List<Map<String, Object>> catList = jdbcTemplate.queryForList(sql.toString());
			int xmlFileNum = new BigDecimal(catList.size()).divide(new BigDecimal("500"), BigDecimal.ROUND_UP).intValue();
			for (int count = 0; count < xmlFileNum; count++) {
				// 開始組合商品資料
				for (Iterator<Map<String, Object>> category = catList.iterator(); category.hasNext();) {
					Map<String, Object> cat = category.next();

					BigDecimal catId = (BigDecimal) cat.get("main_category_id");
					String locationURL = ServerValue.getFrontHostname() + ServerValue.getFrontContextPath()
							+ "/category/category.do?hpp=baiduopen&z=" + catId;

					String catPath[] = StringUtils.split((String) cat.get("category_path"), "/");
					int tagNum = catPath.length;
					String catTagCHN[] = new String[2];// 只要两层
					for (int i = 0; i < 2; i++) {
						catTagCHN[i] = catAll.get(catPath[i]);
					}

					String brandName = (String) cat.get("brand_name");
					BigDecimal prodCount = (BigDecimal) cat.get("pd_count");

					Element url = urlset.addElement("url");
					// 有問題的資料跳過，eg.空白，null
					try {
						// 如果英文拿掉只剩空白，則保留英文
						if (StringUtils.isNotBlank(brandName.replaceAll("[a-zA-Z\\s]", ""))) {
							brandName = brandName.replaceAll("[a-zA-Z\\s]", "");
						}

						url.addElement("loc").addText(locationURL);

						Element data = url.addElement("data");
						Element display = data.addElement("display");

						display.addElement("store").addText("耀点100购物商城");
						display.addElement("store_pic").addText(ServerValue.getImgDomain() + "/images/80x80.jpg");
						display.addElement("tags").addText(StringUtils.join(catTagCHN, "\\"));
						display.addElement("services").addText("百货商城\\诚信满意\\网络商城");
						display.addElement("brand").addText(brandName);
						display.addElement("number").addText(prodCount.toString());

						if (isPromotion1Exist) {
							display.addElement("promotion1").addText(newslist.get(0).getSubject());
							display.addElement("promotion1_url").addText(
									ServerValue.getFrontHostname() + ServerValue.getFrontContextPath() + "/announcement/viewv2.do?annId="
											+ newslist.get(0).getId());
						}
						if (isPromotion2Exist) {
							display.addElement("promotion2").addText(newslist.get(1).getSubject());
							display.addElement("promotion2_url").addText(
									ServerValue.getFrontHostname() + ServerValue.getFrontContextPath() + "/announcement/viewv2.do?annId="
											+ newslist.get(1).getId());
						}
					} catch (Exception e) {
						// 移除產生exception的node
						urlset.elements().remove(urlset.elements().size() - 1);
						logger.info(catId + "," + StringUtils.join(catPath, "\\") + "," + e.getMessage());
					}

				}

				// 移動舊檔案
				Calendar cal = Calendar.getInstance();
				int day = cal.get(Calendar.DAY_OF_WEEK);
				File nowBaibuXMLFolder = new File(ServerValue.getFrontApachePath() + "rds" + File.separatorChar + "baidu"
						+ File.separatorChar);
				File oldBaibuXMLFolder = new File(ServerValue.getFrontApachePath() + "rds" + File.separatorChar + "baidu"
						+ File.separatorChar + day + File.separatorChar);

				if (!nowBaibuXMLFolder.exists()) {
					nowBaibuXMLFolder.mkdirs();
				}
				if (!oldBaibuXMLFolder.exists()) {
					oldBaibuXMLFolder.mkdirs();
				}

				File baibuCatXML = new File(ServerValue.getFrontApachePath() + "rds" + File.separatorChar + "baidu"
						+ File.separatorChar + "cat_" + count + ".xml");
				if (baibuCatXML.exists()) {
					FileUtils.copyFileToDirectory(baibuCatXML, oldBaibuXMLFolder, true);
					FileUtils.forceDelete(baibuCatXML);
				}

				// 產生新檔案
				FileUtils.writeStringToFile(baibuCatXML, baidu.asXML(), "UTF-8");

				baibuCatXMLNameList.add("cat_" + count + ".xml");
			}

			// index
			Document baiduIndex = DocumentHelper.createDocument();
			Element sitemapindex = baiduIndex.addElement("sitemapindex");
			for (Iterator<String> it = baibuCatXMLNameList.iterator(); it.hasNext();) {
				Element sitemap = sitemapindex.addElement("sitemap");
				sitemap.addElement("loc").addText(ServerValue.getFrontHostname() + "/rds/baidu/" + it.next());
				sitemap.addElement("lastmod").addText(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
			}
			File baibuIndexXML = new File(ServerValue.getFrontApachePath() + "rds" + File.separatorChar + "baidu"
					+ File.separatorChar + "baiduCatIndex.xml");
			FileUtils.writeStringToFile(baibuIndexXML, baiduIndex.asXML(), "UTF-8");

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return false;
	}

	private boolean generateProdXMLforBaidu() {
		try {
			Date today = new Date();
			// 第一級和第二級的目錄，作為對照
			Map<String, String> catL1 = new HashMap<String, String>();
			Map<String, String> catL2 = new HashMap<String, String>();
			CommonCriteria cc = new CommonCriteria();
			cc.addEq("isDelete", "N");
			cc.addLe("level", "2");
			cc.addLe("startDate", today);
			cc.addGe("endDate", today);
			List<Category> cats = categoryService.getList(0, -1, cc, new String[] { "level", "id" });
			for (Category cat : cats) {
				if ("0".equals(cat.getLevel())) {
					catL1.put(cat.getId().toString(), cat.getName());
				} else if ("1".equals(cat.getLevel())) {
					catL2.put(cat.getId().toString(), cat.getName());
				}

			}

			StringBuffer sql = new StringBuffer();
			sql.append("select c.product_id, c.product_name, c.product_brief, a.shelf_price, ");
			sql.append("c.product_keyword, a.end_date, b.img_file_path, a.category_path ");
			sql.append("from ec_view_shelf_product a, ");
			sql.append("ec_image_main b, ec_product_main c ");
			sql.append("where a.product_id = c.product_id  ");
			sql.append("and c.product_id = b.product_id  ");
			sql.append("and a.main_category_id in( ");
			sql.append("  select category_id from ec_category_main  ");
			sql.append("  where category_path like ? ");
			sql.append("  and is_delete = 'N' ");
			sql.append("  and sysdate between start_date and end_date) ");
			sql.append("and a.main_category_id = substr(a.v_uk,  (InStr(a.v_uk,'_')) +1 ) ");
			sql.append("and c.is_delete = 'N' ");
			sql.append("and b.image_type='MAIN' ");
			sql.append("and b.img_file_path like '%_m250.jpg' ");
			sql.append("and c.product_name like '%【%】%' ");

			List<Map<String, Object>> shelfProducts = null;
			// 按照第一級目錄，開始組合xml
			for (Iterator<String> it = catL1.keySet().iterator(); it.hasNext();) {
				Document baidu = DocumentHelper.createDocument();
				Element urlset = baidu.addElement("urlset");
				String catL1Id = it.next();
				shelfProducts = jdbcTemplate.queryForList(sql.toString(), new Object[] { catL1Id + "/%" });
				// 開始組合商品資料
				for (Iterator<Map<String, Object>> products = shelfProducts.iterator(); products.hasNext();) {
					Map<String, Object> pd = products.next();

					String productId = (String) pd.get("product_id");
					String productName = (String) pd.get("product_name");
					String productBrand = StringUtils.substringBetween(productName, "【", "】");
					BigDecimal shelfPrice = (BigDecimal) pd.get("shelf_price");
					String productKeywords = StringUtils.replace((String) pd.get("product_keyword"), ",", "\\");
					String productBrief = (String) pd.get("product_brief");
					String[] productCategory = ((String) pd.get("category_path")).split("/");
					String productCategoryL1 = "";
					String productCategoryL2 = "";
					if (productCategory.length > 1) {
						productCategoryL1 = catL1.containsKey(productCategory[0]) ? catL1.get(productCategory[0]) : "";
						productCategoryL2 = catL2.containsKey(productCategory[1]) ? catL2.get(productCategory[1]) : "";
					}

					String productImage = (String) pd.get("img_file_path");
					String productEndDate = new SimpleDateFormat("yyyy-MM-dd").format((Date) pd.get("end_date"));

					// 如果英文拿掉只剩空白，則保留英文
					if (StringUtils.isNotBlank(productBrand.replaceAll("[a-zA-Z\\s]", ""))) {
						productBrand = productBrand.replaceAll("[a-zA-Z\\s]", "");
					}

					Element url = urlset.addElement("url");
					// 有問題的資料跳過，eg.空白，null
					try {
						// 追蹤碼
						// String trackURL = ServerValue.getFrontHostname() + ServerValue.getFrontContextPath()
						// + "/channel/ad.do?id=346&site=baidu&url=";
						// 商品連結
						String productURL = ServerValue.getFrontHostname() + ServerValue.getFrontContextPath()
								+ "/product/product.do?hpp=baiduopen&productId=" + productId;
						// String wholeURL = trackURL + URLEncoder.encode(productURL, "UTF-8");
						url.addElement("loc").addText(productURL);

						Element data = url.addElement("data");
						Element display = data.addElement("display");

						display.addElement("title").addText(productName);
						display.addElement("realtitle").addText(productName);
						display.addElement("price").addText(shelfPrice.toString());
						display.addElement("brand").addText(productBrand);
						display.addElement("tags").addText(productKeywords);
						display.addElement("services").addText("百货商城\\诚信满意\\网络商城");
						display.addElement("image").addText(ServerValue.getImgDomain() + productImage);
						display.addElement("store").addText("耀点100");
						display.addElement("stock").addText("0");
						display.addElement("description").addText(productBrief);
						display.addElement("city").addText("上海");
						display.addElement("firstclass").addText(productCategoryL1);
						display.addElement("secondclass").addText(productCategoryL2);
						display.addElement("expirationdate").addText(productEndDate);
					} catch (Exception e) {
						// 移除產生exception的node
						urlset.elements().remove(urlset.elements().size() - 1);
						logger.info(productId + "," + catL1Id + "," + e.getMessage());
					}
				}
				// 移動舊檔案
				Calendar cal = Calendar.getInstance();
				int day = cal.get(Calendar.DAY_OF_WEEK);
				File nowBaibuXMLFolder = new File(ServerValue.getFrontApachePath() + "rds" + File.separatorChar + "baidu"
						+ File.separatorChar);
				File oldBaibuXMLFolder = new File(ServerValue.getFrontApachePath() + "rds" + File.separatorChar + "baidu"
						+ File.separatorChar + day + File.separatorChar);

				if (!nowBaibuXMLFolder.exists()) {
					nowBaibuXMLFolder.mkdirs();
				}
				if (!oldBaibuXMLFolder.exists()) {
					oldBaibuXMLFolder.mkdirs();
				}

				File baibuXML = new File(ServerValue.getFrontApachePath() + "rds" + File.separatorChar + "baidu"
						+ File.separatorChar + catL1Id + ".xml");
				if (baibuXML.exists()) {
					FileUtils.copyFileToDirectory(baibuXML, oldBaibuXMLFolder, true);
					FileUtils.forceDelete(baibuXML);
				}

				// 產生新檔案
				FileUtils.writeStringToFile(baibuXML, baidu.asXML(), "UTF-8");

			}
			// index
			Document baiduIndex = DocumentHelper.createDocument();
			Element sitemapindex = baiduIndex.addElement("sitemapindex");
			for (Iterator<String> it = catL1.keySet().iterator(); it.hasNext();) {
				Element sitemap = sitemapindex.addElement("sitemap");
				sitemap.addElement("loc").addText(ServerValue.getFrontHostname() + "/rds/baidu/" + it.next() + ".xml");
				sitemap.addElement("lastmod").addText(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
			}
			File baibuIndexXML = new File(ServerValue.getFrontApachePath() + "rds" + File.separatorChar + "baidu"
					+ File.separatorChar + "baiduIndex.xml");
			FileUtils.writeStringToFile(baibuIndexXML, baiduIndex.asXML(), "UTF-8");

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		return true;
	}

	@SuppressWarnings("unchecked")
	@Override
	public boolean generateBrandIndex(String date) throws CoreException, IOException {
		StringBuffer sb = new StringBuffer();
		sb.append("select bt.id, bt.n, bt.sn, bt.en ");
		sb.append("from(select brand_id id, brand_name n, UPPER(brand_ename) sn, brand_ename en ");
		sb.append("from ec_brand_main where brand_ename is not null and brand_status = 'Y' ");
		sb.append("union ");
		sb.append("select brand_id id, brand_name n, UPPER(brand_name) sn, brand_ename en ");
		sb.append("from ec_brand_main ");
		sb.append("where brand_ename is null and lengthb(substr(brand_name, 0,1)) = 1 and brand_status = 'Y' ");
		sb.append("union ");
		sb.append("select brand_id id, brand_name n,F_PINYIN(brand_name) sn, brand_ename en ");
		sb.append("from ec_brand_main ");
		sb.append("where brand_ename is null and lengthb(substr(brand_name, 0,1)) = 3 and brand_status = 'Y' ) bt, ");
		sb.append("(Select Distinct(Brand_Id) From Tmp_Search_Product) Pb ");
		sb.append("Where Bt.Id = Pb.Brand_Id order by bt.sn ");

		List list = getDao().getSQLQueryByList(sb.toString(), null, 0, -1);
		if (!list.isEmpty()) {
			Object[] objs = list.toArray();
			List<Object> objList = new ArrayList<Object>();
			List<Object> otherList = new ArrayList<Object>();
			Map<String, Object> brandMap = new HashMap<String, Object>();
			String now = "A";
			for (int iOd = 0; iOd < objs.length; iOd++) {
				Object[] obj2 = (Object[]) objs[iOd];
				if (obj2[2].toString().charAt(0) < 'A' || obj2[2].toString().charAt(0) > 'Z') {
					otherList.add(obj2);
				} else {
					if (!obj2[2].toString().substring(0, 1).equals(now)) {
						brandMap.put(now, objList);
						objList = new ArrayList<Object>();
						now = obj2[2].toString().substring(0, 1);
					}
					objList.add(obj2);
				}
			}
			brandMap.put(now, objList);
			Map<String, Object> m = new HashMap<String, Object>();
			m.put("brandMap", brandMap);
			m.put("others", otherList);
			FileUtils.writeStringToFile(new File(ServerValue.getFrontContentHtmlPath() + File.separator + "COMMON"
					+ File.separator + "BRAND_INDEX.html"), templateService.format("static_BrandIndex", m));
		}
		return true;
	}

	@Override
	@Transactional(readOnly = false)
	public void generateIdxMidBoxAdv_V3(String date) throws CoreException {
		boolean result = deleteFilesOfPosition(ServerValue.getFrontContentHtmlPath() + "IDX", "IDX_SALE_V3");
		if (result) {
			CommonCriteria criteria = new CommonCriteria();
			criteria.addEq("advType", "IDX_SALE_V3");
			generateMidBoxAdv_V2(criteria, "static_MidBox_V3");
		}
	}

	// 首頁通欄廣告
	@Override
	@Transactional(readOnly = false)
	public boolean generateIdxTopSpanAdv() throws CoreException, Exception {
		return generateIdxImageAdv("IDX_TOPSPAN");
	}

	// 首頁腰線廣告
	@Override
	@Transactional(readOnly = false)
	public boolean generateIdxWaistline() throws CoreException, Exception {
		return generateIdxImageAdv("IDX_WAISTLINE");
	}

	// 首頁右側小廣告1
	@Override
	@Transactional(readOnly = false)
	public boolean generateIdxRightSmall1() throws CoreException, Exception {
		return generateIdxImageAdv("IDX_RIGHTSMALL1");
	}

	// 首頁右側小廣告2
	@Override
	@Transactional(readOnly = false)
	public boolean generateIdxRightSmall2() throws CoreException, Exception {
		return generateIdxImageAdv("IDX_RIGHTSMALL2");
	}

	// 首頁雙拼廣告左
	@Override
	@Transactional(readOnly = false)
	public boolean generateIdxTwinLeft() throws CoreException, Exception {
		return generateIdxImageAdv("IDX_TWINLEFT");
	}

	// 首頁雙拼廣告右
	@Override
	@Transactional(readOnly = false)
	public boolean generateIdxTwinRight() throws CoreException, Exception {
		return generateIdxImageAdv("IDX_TWINRIGHT");
	}

	// 首頁圖片廣告
	@Override
	@Transactional(readOnly = false)
	public boolean generateIdxImageAdv(String advType) throws Exception {
		return new IdxImageAdvGenerater(this).generateIdxImageAdv(advType);
	}

	@Override
	@Transactional(readOnly = false)
	public boolean generateIdxImageAdv(String advType, String advType2) throws Exception {
		Menu menu = menuService.get("SystemValue");
		return new IdxImageAdvGenerater(this).generateIdxImageAdv(menu.getOptions().get("pclady").getMemo1(), advType,
				advType2);
	}

	// 首頁本週推薦
	@Override
	@Transactional(readOnly = false)
	public boolean generateIdxWeeklyRecommendAdv() throws Exception {
		return new IdxWeeklyRecommendAdvGenerater(this).generateIdxWeeklyRecommendAdv();
	}

	@SuppressWarnings("unchecked")
	@Override
	public void generateSideBarMenu2New(String date) throws CoreException, IOException {
		// try {

		List<Category> categories = categoryService.getSideBarAvailableCategory();
		Object[] obj = splitCategory(categories);
		Map<Long, Category> cats = (Map<Long, Category>) obj[0];
		Map<Long, List<Category>> childcats = (Map<Long, List<Category>>) obj[1];
		for (Category cat : categories) {
			Map<String, Object> sidebarMap = new HashMap<String, Object>();
			sidebarMap.put("contentPath", ServerValue.getFrontContextPath());
			String catLevel = StringUtils.defaultString(cat.getLevel(), "0").trim();
			sidebarMap.put("category", cat);

			boolean isOutlets = cat.getCategoryPath().startsWith("7447");
			sidebarMap.put("isOutlets", isOutlets);

			Long catId = cat.getId();
			String catIsEndNode = cat.getIsEndnode().trim();
			if ("Y".equals(catIsEndNode)) { // 底層
				if (isOutlets) {
					generateSidebarAfterSecondLevel2New(cat, cat, sidebarMap, cats, childcats, isOutlets);
				} else {
					generateSidebarAfterSecondLevel2New(cat, cats.get(cat.getParentId()), sidebarMap, cats, childcats, isOutlets);
				}

				StringBuffer naviBatFilePath = new StringBuffer(ServerValue.getFrontContentHtmlPath()).append(File.separator)
						.append(cat.getId()).append(File.separator).append("SIDEBAR.html");
				FileUtils.writeStringToFile(new File(naviBatFilePath.toString()), templateService.format("static_sidebar_lv2",
						sidebarMap));
			} else if ("0".equals(catLevel)) {// 館首頁
				// 子目錄一
				List<Category> subCategories = childcats.get(catId);
				if (null == subCategories) {
					continue;
				}
				List<Category> tmpCategories = new ArrayList<Category>();
				for (Category subCat : subCategories) {
					if ("N".equals(subCat.getIsBrand().trim()) && "N".equals(subCat.getIsPromotion().trim())) {
						tmpCategories.add(subCat);
					}
				}
				sidebarMap.put("subCategories", tmpCategories);

				Hashtable<Long, List<Category>> catH = new Hashtable<Long, List<Category>>();
				for (Iterator<Category> it = subCategories.iterator(); it.hasNext();) {
					Category subCat = it.next();

					// 子目錄二
					List<Category> secondSubCategories = childcats.get(subCat.getId());
					if (subCat.getId() == 3500) {
						// System.out.println("sec:"+secondSubCategories)
					}
					if (null == secondSubCategories) {
						continue;
					}
					tmpCategories = new ArrayList<Category>();
					for (Category nextLevelCat : secondSubCategories) {
						if ("N".equals(nextLevelCat.getIsBrand().trim()) && "N".equals(nextLevelCat.getIsPromotion().trim())) {
							tmpCategories.add(nextLevelCat);
						}
					}
					catH.put(subCat.getId(), tmpCategories);
				}
				sidebarMap.put("catH", catH);
				StringBuffer naviBatFilePath = new StringBuffer(ServerValue.getFrontContentHtmlPath()).append(File.separator)
						.append(cat.getId()).append(File.separator).append("SIDEBAR.html");
				FileUtils.writeStringToFile(new File(naviBatFilePath.toString()), templateService.format("static_sidebar_lv1",
						sidebarMap));
			} else {
				generateSidebarAfterSecondLevel2New(cat, cat, sidebarMap, cats, childcats, isOutlets);
				StringBuffer naviBatFilePath = new StringBuffer(ServerValue.getFrontContentHtmlPath()).append(File.separator)
						.append(cat.getId()).append(File.separator).append("SIDEBAR.html");
				FileUtils.writeStringToFile(new File(naviBatFilePath.toString()), templateService.format("static_sidebar_lv2",
						sidebarMap));
			}
		}
	}

	private Object[] splitCategory(List<Category> categories) {
		Object[] obj = new Object[2];
		Map<Long, List<Category>> ccats = new HashMap<Long, List<Category>>();
		Map<Long, Category> cats = new HashMap<Long, Category>();
		List<Category> temp;
		for (Category cat : categories) {
			cats.put(cat.getId(), cat);

			if (ccats.containsKey(cat.getParentId())) {
				temp = ccats.get(cat.getParentId());
			} else {
				temp = new ArrayList<Category>();
			}
			temp.add(cat);
			ccats.put(cat.getParentId(), temp);

		}
		obj[0] = cats;
		obj[1] = ccats;
		return obj;
	}

	void generateSidebarAfterSecondLevel2New(Category nowCat, Category genThisCategory, Map<String, Object> sidebarMap,
			Map<Long, Category> cats, Map<Long, List<Category>> childcats, boolean isOutlets) throws CoreException {
		if (null == nowCat || null == genThisCategory) {
			return;
		}
		sidebarMap.put("genThisCategory", genThisCategory);
		List<Category> sameLevelCategories = childcats.get(genThisCategory.getParentId());
		if (null == sameLevelCategories) {
			return;
		}
		List<Category> subCategoriesNormal = new ArrayList<Category>();
		Hashtable<Long, List<Category>> catHNormal = new Hashtable<Long, List<Category>>();
		List<Category> subCategoriesPromote = new ArrayList<Category>();
		List<Category> subCategoriesBrand = new ArrayList<Category>();
		Hashtable<Long, List<Category>> empty = new Hashtable<Long, List<Category>>();

		for (Category sameLevelCat : sameLevelCategories) {
			// 商品分类
			if (("N".equals(sameLevelCat.getIsBrand().trim()) && "N".equals(sameLevelCat.getIsPromotion().trim()))
					|| (nowCat.getParentId().equals(sameLevelCat.getId()) || sameLevelCat.getId().equals(nowCat.getId()))) {
				if (isOutlets) {// 品牌折扣馆
					if (nowCat.getLevel().equals("1")) {// 品牌折扣馆的品牌分类
						// 只gen自己这一层的分类其馀同一层的不gen，因为不一定有活动
						if (nowCat.getCategoryPath().equals(sameLevelCat.getCategoryPath())) {
							subCategoriesNormal.add(sameLevelCat);
						}
					} else {
						subCategoriesNormal.add(sameLevelCat);
					}
				} else {
					subCategoriesNormal.add(sameLevelCat);
				}
			}
			List<Category> subCategories = childcats.get(sameLevelCat.getId());
			if (null == subCategories) {
				continue;
			}
			List<Category> tmpCategories = new ArrayList<Category>();
			for (Category nextLevelCat : subCategories) {
				if (nowCat.getParentId().equals(sameLevelCat.getId()) || sameLevelCat.getId().equals(nowCat.getId())) {
					if ("Y".equals(nextLevelCat.getIsPromotion().trim())) {// 活动特辑
						subCategoriesPromote.add(nextLevelCat);
					}
					if ("Y".equals(nextLevelCat.getIsBrand().trim())) {// 品牌分类
						subCategoriesBrand.add(nextLevelCat);
					}
				}
				if ("N".equals(nextLevelCat.getIsBrand().trim()) && "N".equals(nextLevelCat.getIsPromotion().trim())) {
					tmpCategories.add(nextLevelCat);
				}
			}
			catHNormal.put(sameLevelCat.getId(), tmpCategories);
		}
		sidebarMap.put("subCategoriesPromote", subCategoriesPromote);
		sidebarMap.put("empty", empty);
		sidebarMap.put("subCategoriesBrand", subCategoriesBrand);
		sidebarMap.put("subCategoriesNormal", subCategoriesNormal);
		sidebarMap.put("catHNormal", catHNormal);
	}

	/**
	 * 分線維護權限檢核
	 * 
	 * @param commcriteria
	 * @return
	 */
	CommonCriteria addPermissionCrit(CommonCriteria criteria) {
		User user = AdminHelper.getUser();
		if (null != user) {
			int permissionSize = user.getPermissions(Type.CATEGORY).size();
			if (permissionSize > 0) {
				if (null == criteria) {
					criteria = new CommonCriteria();
				}
				// 若 user 是 PM部門, 檢核 product.category 的 orgnizationPath 是否合乎規定
				List<Serializable> prs = new ArrayList<Serializable>();
				for (UserPermission up : user.getPermissions(Type.CATEGORY).values()) {
					prs.add(Long.parseLong(up.getPermissionCode()));
				}
				criteria.addIn("mainCateId", prs);
			}
		}
		return criteria;
	}

	// 四头标
	@Override
	@Transactional(readOnly = false)
	public boolean generateTop4Tag() throws Exception {
		return new Top4TagGenerater(this).generateTop4Tag();
	}

	// 热销商品
	@Override
	@Transactional(readOnly = false)
	public boolean generaterIdxHotSaleV5() throws CoreException, Exception {
		return new IdxHotSaleV5Generater(this, generateNotifyService).generaterIdxHotSaleV5();
	}

	@Override
	@Transactional(readOnly = false)
	public boolean generaterPclHotSaleV5() throws CoreException, Exception {
		Menu menu = menuService.get("SystemValue");
		return new IdxHotSaleV5Generater(this, generateNotifyService).generaterIdxHotSaleV5(menu.getOptions().get("pclady")
				.getMemo1(), "PCL_HOTSALE_V5");
	}

	// 活动特辑
	@Override
	@Transactional(readOnly = false)
	public boolean generaterIdxSpecialAct() throws CoreException, Exception {
		return new IdxSpecialActGenerater(this, generateNotifyService).generaterIdxSpecialAct();
	}

	@Override
	@Transactional(readOnly = false)
	public boolean generaterPclSpecialAct() throws CoreException, Exception {
		Menu menu = menuService.get("SystemValue");
		return new IdxSpecialActGenerater(this, generateNotifyService).generaterIdxSpecialAct(menu.getOptions().get(
				"pclady").getMemo1(), "PCL_SPECIAL_ACT");
	}

	// 主题促销
	@Override
	@Transactional(readOnly = false)
	public boolean generaterIdxSaleV5() throws CoreException, Exception {
		return new IdxSaleV5Generater(this, generateNotifyService).generaterIdxSaleV5();
	}

	@Override
	@Transactional(readOnly = false)
	public boolean generaterPclSaleV5() throws CoreException, Exception {
		Menu menu = menuService.get("SystemValue");
		return new IdxSaleV5Generater(this, generateNotifyService).generaterIdxSaleV5(menu.getOptions().get("pclady")
				.getMemo1(), "PCL_SALE_V5");
	}

	// 品牌推荐
	@Override
	@Transactional(readOnly = false)
	public boolean generaterIdxBrandRecommend() throws CoreException, Exception {
		return new IdxBrandRecommendGenerater(this, generateNotifyService).generaterIdxBrandRecommend();
	}

	@Override
	@Transactional(readOnly = false)
	public boolean generaterPclBrandRecommend() throws CoreException, Exception {
		Menu menu = menuService.get("SystemValue");
		return new IdxBrandRecommendGenerater(this, generateNotifyService).generaterIdxBrandRecommend(menu.getOptions()
				.get("pclady").getMemo1(), "PCL_BRAND_RECOMMEND");
	}

	@Override
	@Transactional(readOnly = false)
	public boolean generateEventHtml(Map map, String fileName, String templateName) throws CoreException {
		String sql;
		List<Map<String, Object>> templateContent;
		try {
			if (StringUtils.isNotBlank(templateName)) {
				File file = new File(fileName);
				Map<String, Object> excelContent = new HashMap<String, Object>();
				excelContent.put("map", map);
				sql = "SELECT TEMPLATE_CONTENT FROM EC_TEMPLATE_ITEM WHERE TEMPLATE_NAME = ?";
				templateContent = jdbcTemplate.queryForList(sql, templateName);
				if (templateContent.size() == 1) {
					String fileContent = templateService.formatByStringTemplate(templateContent.get(0).get("TEMPLATE_CONTENT")
							.toString(), excelContent);
					FileUtils.writeStringToFile(file, fileContent, "UTF-8");
					sql = "INSERT INTO EC_TEMPLATE_LOG (ID,CREATE_DATE,TEMPLATE_NAME,FILE_NAME,MAP_CONTENT,TEMPLATE_CONTENT) VALUES (SEQ_EC_TEMPLATE_LOG.NEXTVAL,sysdate,?,?,?,?)";
					jdbcTemplate.update(sql, new Object[] { templateName, fileName, map.toString(),
							templateContent.get(0).get("TEMPLATE_CONTENT").toString() });
					return true;
				} else if (templateContent.size() == 0) {
					logger.info("產生資料錯誤,找不到符合templateContent,templateName = " + templateName);
					return false;
				} else {
					logger.info("產生資料錯誤,找到多筆templateContent,templateName = " + templateName);
					return false;
				}
			} else {
				logger.info("產生資料錯誤,fileName為空值,fileName = " + fileName + ",templateName=" + templateName);
				return false;
			}
		} catch (Exception e) {
			logger.info("資料嵌入错误:" + e.getMessage());
			return false;
		}
	}
}